Home > Back-end >  Customize DataGridView filled by linq-query
Customize DataGridView filled by linq-query

Time:03-01

I have 2 SQL-Tables, which I created via SQL Server Managment Studio (including PK & FK):

sql-tables

In my WinForm Project in Visual Studio, I added the data-model via Code First to an Existing Database and read the data via the following linq-query:

dataGridView1.DataSource = dbContext.deliveries.OrderBy(d => d.id).ToList();

Now the datagridView1 consists of the columns from the table "deliveries", but instead of showing a column customer_id I would like show the corresponding name and adress of the customer.

Some other answers on stackoverflow suggest to edit the query and use the "include" property. So I tried to use

deliveries.Include(d=>d.customer.name).OrderBy(d => d.id).ToList();

but this throws an Exception while running with the folowing Error:

The EntityType '*.customer' does not declare a navigation property with the name 'name'

which I dont understand, since my Classes follow the form of https://docs.microsoft.com/en-us/ef/ef6/fundamentals/relationships AND are created via Code First from existing database.

      public partial class deliveries
    {
        public int id { get; set; }

        public int? amount { get; set; }
        
        public int? customer_id { get; set; }
        [ForeignKey("customer_id")]
        public virtual customer customer { get; set; }

    }
   public partial class customer
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public customer()
        {
            deliveries = new HashSet<deliveries>();
        }
        [Key]
        public int customerID { get; set; }

        [StringLength(50)]
        public string name { get; set; }

        [StringLength(10)]
        public string address { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<deliveries> deliveries { get; set; }
    }

CodePudding user response:

If you want to show only specific values, you have to do custom projection and specify shape of your result via Select. It can be DTO or anonymous class, and no Includes are needed.

var result = deliveries
    .OrderBy(d => d.id)
    .Select(d => new 
    {
        d.customer.name,
        d.customer.address
    })
    .ToList();

CodePudding user response:

Why is deliveries.Include(d=>d.customer.name) wrong?
according to docs, the included parameter is an related Entity, not an simple type. Find more about eager loading

The simplest way to solve:

  dataGridView1.DataSource = dbContext.deliveries
                              .Include(x => x.customer)
                              .Select new(x => 
                               {
                                 Id = x.id,
                                 CustomerName = x.customer.name,
                                 //more properties you want to display
                               })
                              .OrderBy(x => x.id).ToList();

Note:

  1. according to @Svyatoslav Danyliv the Include can be omitted.
  2. Maybe you didn't paste your actual code, but classes and properties should follow good naming convension.
  • Related