简体   繁体   中英

Entity Framework with Include statement to select 3rd level specific fields

I searched a lot to find a similar case but with no luck.

My data resides in SQL Server 2014 and the app running against EF version: 6.

Below is the model structure/relationship:

Supplier -- 1:m -- Receipt -- 1:m -- ReceiptItem -- m:1 -- Item

Model classes:

public partial class Supplier
{
    public Supplier()
    {
        this.Receipts = new HashSet<Receipt>();
    }

    public int supplierId { get; set; }
    public string supplierName { get; set; }
    public string supplierPhone { get; set; }
    public string supplierAddress { get; set; }
    public string supplierRemark { get; set; }

    public virtual ICollection<Receipt> Receipts { get; set; }
}

public partial class Receipt
{
    public Receipt()
    {
        this.ReceiptItems = new HashSet<ReceiptItem>();
    }

    public int receiptId { get; set; }
    public int supplierId { get; set; }
    public Nullable<System.DateTime> receiptDate { get; set; }

    public virtual Supplier Supplier { get; set; }
    public virtual ICollection<ReceiptItem> ReceiptItems { get; set; }
}

public partial class ReceiptItem
{
    public int receiptId { get; set; }
    public int itemId { get; set; }
    public short itemQnty { get; set; }
    public double itemCost { get; set; }  

    public virtual Item Item { get; set; }
    public virtual Receipt Receipt { get; set; }
}

public partial class Item
{
    public Item()
    {
        this.ReceiptItems = new HashSet<ReceiptItem>();
    }

    public int itemId { get; set; }
    public string itemName { get; set; }
    public string itemPackage { get; set; }
    public string itemCategory { get; set; }

    public virtual ICollection<ReceiptItem> ReceiptItems { get; set; }
}

The output needed is:

 {"receiptId": 9,
"supplierId": 1,
"supplierName": “SomeOne”, // << to be grabbed from the (Supplier) entity
"receiptDate": "2017-03-05T17:54:49.573",
"ReceiptItems": [{
    "itemId": 1,
    "receiptId": 9,
    "itemName": "item A",  // << to be grabbed from the (Item) entity
    "itemQnty": 4,
    "itemCost": 30.0
  },{
    "itemId": 2,
    "receiptId": 9,
    "itemName": "item B",  // << to be grabbed from the (Item) entity
    "itemQnty": 7,
    "itemCost": 50.0
  }]
}

The context has lazy loading disabled ( Configuration.LazyLoadingEnabled = false; ). And I'm trying to execute the following:

var receipt = await db.Receipts
                      .Where(r => r.receiptId.Equals(intQryTerm))
                      .Include(r => r.Supplier)
                      .Include(r => r.ReceiptItems)
                      .Include(r => r.ReceiptItems.Select(receiptItem => receiptItem.Item)) 
                      .FirstOrDefaultAsync();

But it gives me a mess! (lot of sub-levels).

What I need is the same structure as illustrated above (with no more inheritance).

Your help is appreciated!

Five days passed and no answer has been posted!
Meanwhile I was spending several hours in searching for some resources that could help, and trying plenty of techniques...
Although the question asks for Include statement but as the output needed does not stick to the model classes (Receipt includes extra property "supplierName and ReceiptItem includes extra property itemName), I surprised how easy and clean the code can be and even without using the "Include" statement .
Here is the code:

var receipt = await db.Receipts
        .Where(r => r.receiptId.Equals(receiptId))
        .Select(r => new
            {
                r.receiptId,
                r.receiptDate,
                r.supplierId,
                r.Supplier.supplierName,
                ReceiptItems = r.ReceiptItems
                                    .Select(ReceiptItem => new
                                        {
                                        ReceiptItem.itemId,
                                        ReceiptItem.Item.itemName,
                                        ReceiptItem.itemPackage,
                                        ReceiptItem.itemQnty,
                                        ReceiptItem.itemCost
                                        }
                                    )
            }
        )
       .FirstOrDefaultAsync();

The code generated with help from LINQPad (it's really great tool and I advice you guys to put it in use for your development, you can use the FREE version)

Hopefully this will help you in case you experienced such challenge.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM