New to Telerik UI for WinFormsStart a free 30-day trial

Binding RadGridView to Entity Framework Using Code First Approach

Updated over 6 months ago
Product VersionProductAuthorLast modified
2015.3.930RadGridView for WinFormsHristo MerdjanovOctober 30, 2015

Problem

Entity Framework`s Database First approach provides very little control over the models used in the application. It automatically generates a lot of files which should not be altered and at times versioning of the database becomes very difficult.

Solution

The Code First approach, on the other hand, delivers exactly the opposite. That is why, especially in recent times and for new projects, the developer community chooses this way to interact with SQL Server. Another great advantage is that the database can be entirely managed by the application. Changes in the models are also automatically reflected by the ORM engine at the end migrated to the database itself.

We are going to take this example project even further by implementing Repository Pattern and Unit of Work. Our implementation consists of three projects each defining a separate layer of the application.

  • RadGridViewEFCodeFirst.Models – responsible for the business objects
  • RadGridViewEFCodeFirst.Data – data layer for connecting to SQL Server
  • RadGridViewEFCodeFirst.WinFormsClient – client demo application

Our RadGridViewcontrol will be setup in hierarchy and the screenshot below shows the result at the end: radgridview-ef-code-first

1.In our Models project, let`s first define several business objects:

C#
public class OrderType
{
    private ICollection<Order> orders;
    private ICollection<Shipper> shippers;
 
    public OrderType()
    {
        this.orders = new HashSet<Order>();
        this.shippers = new HashSet<Shipper>();
    }
 
    public int OrderTypeId { get; set; }
 
    public virtual ICollection<Order> Orders
    {
        get
        {
            return this.orders;
        }
        set
        {
            this.orders = value;
        }
    }
 
    public virtual ICollection<Shipper> Shippers
    {
        get
        {
            return this.shippers;
        }
        set
        {
            this.shippers = value;
        }
    }
 
    public string  Description { get; set; }
}
C#
public class Order
{
    public int OrderId { get; set; }
 
    public int OrderTypeId { get; set; }
 
    public virtual OrderType OrderType { get; set; }
 
    public string Description  { get; set; }
 
    public bool IsFinished { get; set; }
}
C#
public class Shipper
{
    public int ShipperId { get; set; }
 
    public int OrderTypeId { get; set; }
 
    public virtual OrderType OrderType { get; set; }
 
    public string Name { get; set; }
 
    public string Address { get; set; }
}

2.Now, in our Data project we have to define the interfaces needed by the Repository Pattern and define the common functionality:

C#
public interface IGenericRepository<T> where T : class
{
    IQueryable<T> All();
 
    IQueryable<T> SearchFor(Expression<Func<T, bool>> conditions);
 
    void Add(T entity);
 
    void Update(T entity);
 
    void Delete(T entity);
 
    void Detach(T entity);
}
C#
public interface IRadGridViewEFCodeFirstContext
{
    IDbSet<Order> Orders { get; set; }
 
    IDbSet<OrderType> OrderTypes { get; set; }
 
    IDbSet<Shipper> Shippers { get; set; }
 
    IDbSet<T> Set<T>() where T : class;
 
    DbEntityEntry<T> Entry<T>(T entity) where T : class;
 
    void SaveChanges();
}
C#
public interface IRadGridViewEFCodeFirstData
{
    IGenericRepository<Order> Orders { get; }
 
    IGenericRepository<OrderType> OrderTypes { get; }
 
    IGenericRepository<Shipper> Shippers { get; }
 
    void SaveChanges();
}

3.Let us now implement our repositories and data layer:

C#
public class RadGridViewEFCodeFirstContext : DbContext, IRadGridViewEFCodeFirstContext
{
    public RadGridViewEFCodeFirstContext()
        : base("RadGridViewEFCodeFirstConnection")
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<RadGridViewEFCodeFirstContext, Configuration>());
    }
 
    public IDbSet<Order> Orders { get; set; }
 
    public IDbSet<OrderType> OrderTypes  { get; set; }
 
    public IDbSet<Shipper> Shippers { get; set; }
 
    public new IDbSet<T> Set<T>() where T : class
    {
        return base.Set<T>();
    }
 
    public new void SaveChanges()
    {
        base.SaveChanges();
    }
}
C#
public class RadGridViewEFCodeFirstRepository<T> : IGenericRepository<T> where T : class
{
    private IRadGridViewEFCodeFirstContext context;
    private IDbSet<T> set;
 
    public RadGridViewEFCodeFirstRepository(IRadGridViewEFCodeFirstContext context)
    {
        this.context = context;
        this.set = context.Set<T>();
    }
 
    public IQueryable<T> All()
    {
        return this.set.AsQueryable();
    }
 
    public IQueryable<T> SearchFor(Expression<Func<T, bool>> conditions)
    {
        return this.All().Where(conditions);
    }
 
    public void Add(T entity)
    {
        this.set.Add(entity);
    }
 
    public void Update(T entity)
    {
        var entry = AttachIfDetached(entity);
        entry.State = EntityState.Modified;
    }
 
    public void Delete(T entity)
    {
        var entry = AttachIfDetached(entity);
        entry.State = EntityState.Deleted;
    }
 
    public void Detach(T entity)
    {
        var entry = this.context.Entry(entity);
        entry.State = EntityState.Detached;
    }
 
    private DbEntityEntry AttachIfDetached(T entity)
    {
        var entry = this.context.Entry(entity);
        if (entry.State == EntityState.Detached)
        {
            this.set.Attach(entity);
        }
 
        return entry;
    }
}
C#
public class RadGridViewEFCodeFirstData : IRadGridViewEFCodeFirstData
{
    private IRadGridViewEFCodeFirstContext context;
    private IDictionary<Type, object> repositories;
 
    public RadGridViewEFCodeFirstData()
        : this(new RadGridViewEFCodeFirstContext())
    {
    }
 
    public RadGridViewEFCodeFirstData(IRadGridViewEFCodeFirstContext context)
    {
        this.context = context;
        this.repositories = new Dictionary<Type, object>();
    }
 
    public IGenericRepository<Order> Orders
    {
        get
        {
            return this.GetRepository<Order>();
        }
    }
 
    public IGenericRepository<OrderType> OrderTypes
    {
        get
        {
            return this.GetRepository<OrderType>();
        }
    }
 
    public IGenericRepository<Shipper> Shippers
    {
        get
        {
            return this.GetRepository<Shipper>();
        }
    }
 
    public void SaveChanges()
    {
        this.context.SaveChanges();
    }
 
    private IGenericRepository<T> GetRepository<T>() where T : class
    {
        var typeOfModel = typeof(T);
        if (!this.repositories.ContainsKey(typeOfModel))
        {
            Type type = typeof(RadGridViewEFCodeFirstRepository<T>);
            this.repositories.Add(typeOfModel, Activator.CreateInstance(type, this.context));
        }
 
        return (IGenericRepository<T>)this.repositories[typeOfModel];
    }
}

4.We also need to define a static class which will generate our sample data:

C#
public class DataGenerator
{
    public static void PopulateData(IRadGridViewEFCodeFirstData data)
    {
        for (int i = 1; i <= 100; i++)
        {
            OrderType orderType = new OrderType()
            {
                OrderTypeId = i,
                Description = "Test" + i
            };
 
            Order order = new Order()
            {
                OrderId = i,
                Description = "Description" + i,
                OrderTypeId = orderType.OrderTypeId
            };
 
            Shipper shipper = new Shipper()
            {
                ShipperId = i,
                Name = "Name " + i,
                OrderTypeId = orderType.OrderTypeId,
                Address = "Address " + i,
            };
 
            data.OrderTypes.Add(orderType);
            data.Orders.Add(order);
            data.Shippers.Add(shipper);
 
            if (i % 100 == 0)
            {
                data.SaveChanges();
            }
        }
 
        data.SaveChanges();
    }
}

5.In our client application we will setup the RadGridView control in hierarchy feeding the templates with data coming from different repositories:

C#
public partial class Form1 : Form
{
    private IRadGridViewEFCodeFirstData data;
 
    public Form1()
    {
        InitializeComponent();
 
        this.data = new RadGridViewEFCodeFirstData();
        if (!data.OrderTypes.All().Any() || !data.Orders.All().Any() || !data.Shippers.All().Any())
        {
            DataGenerator.PopulateData(this.data);
        }
 
        this.SetUpGrid();
        this.FormClosing += Form1_FormClosing;
    }
 
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        this.data.SaveChanges();
    }
 
    private void SetUpGrid()
    {
        ((IDbSet<OrderType>)this.data.OrderTypes.All()).Load();
        this.radGridView1.DataSource = ((IDbSet<OrderType>)this.data.OrderTypes.All()).Local.ToBindingList();
        this.radGridView1.Columns["Orders"].IsVisible = false;
        this.radGridView1.Columns["Shippers"].IsVisible = false;
        this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
 
        GridViewTemplate ordersTemplate = new GridViewTemplate();
        ordersTemplate.Caption = "Orders";
        radGridView1.MasterTemplate.Templates.Add(ordersTemplate);
        ((IDbSet<Order>)this.data.Orders.All()).Load();
        ordersTemplate.DataSource = ((IDbSet<Order>)this.data.Orders.All()).Local.ToBindingList();
        ordersTemplate.Columns["OrderType"].IsVisible = false;
        ordersTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
 
        GridViewRelation relation = new GridViewRelation(radGridView1.MasterTemplate);
        relation.ChildTemplate = ordersTemplate;
        relation.RelationName = "OrderTypesOrders";
        relation.ParentColumnNames.Add("OrderTypeId");
        relation.ChildColumnNames.Add("OrderTypeId");
        radGridView1.Relations.Add(relation);
 
        GridViewTemplate shippersTemplate = new GridViewTemplate();
        shippersTemplate.Caption = "Shippers";
        radGridView1.MasterTemplate.Templates.Add(shippersTemplate);
        ((IDbSet<Shipper>)this.data.Shippers.All()).Load();
        shippersTemplate.DataSource = ((IDbSet<Shipper>)this.data.Shippers.All()).Local.ToBindingList();
        shippersTemplate.Columns["OrderType"].IsVisible = false;
        shippersTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
 
        GridViewRelation relation2 = new GridViewRelation(radGridView1.MasterTemplate);
        relation2.ChildTemplate = shippersTemplate;
        relation2.RelationName = "OrderTypesShippers";
        relation2.ParentColumnNames.Add("OrderTypeId");
        relation2.ChildColumnNames.Add("OrderTypeId");
        radGridView1.Relations.Add(relation2);
    }
}

You can download a complete VB and C# project from the following link.

In this article
ProblemSolution
Not finding the help you need?
Contact Support