实体框架 - 加载嵌套实体

时间:2014-05-02 15:01:57

标签: linq entity-framework poco dbcontext

我花了3个小时在互联网上搜索,需要更好的想法如何实现我的需要。我的实体关系如下(注意:关系,而不是实际域)

class Person
{
    int Id {get;set;}
    string Name {Get;set;}
    virtual DbSet<Order> Orders {get;set;}
}

class Order
{
    int OrderId {get;set;}
    Person Person {get;set;}
    virtual DbSet<Item> Items {get;set;}
}

class Item
{
    int ItemId{get;set;}
    Order Order {get;set;}
}

我需要做的是从数据库中查询这些内容并将它们存储到Dictionary中,而Dictionary又存储在缓存中。我选择存储为字典,因为程序需要定期按人名

执行获取项目
Dictionary<string, Item>

这是我到目前为止所做的。

1)基本的Linq 2 SQL。这样做的问题是字典值被创建为代理,并且在从缓存加载后遍历Item字典时导致程序失败,因为ObjectContext已关闭。

using(var context = new myContext(dbFactory.Create(), contextOwnsConnection: true))
{
var itemLookup = context.Items
             .Include(p=>p.Order.Person)
            .AsNoTracking()
            .GroupBy(p => p.Order.Person.Name)
            .ToDictionary(key=>key.Key, val=> val.ToList());
}

2)禁用代理创建。我从列表中得到了我想要的东西,但是没有设置嵌套实体(Person,Order)(即Item.Order = null)

context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
var itemLookup = context.Items
             .Include(p=>p.Order.Person)
            .AsNoTracking()
            .GroupBy(p => p.Order.Person.Name)
            .ToDictionary(key=>key.Key, val=> val.ToList());

我已经尝试了一些其他的东西,比如包括.Include(“Order.Person”),GroupJoin(我觉得它太难读了)。现在,我知道我可以用另外两个选项解决这个问题:

1)将三个实体加载为字典(对每个实体进行适当的过滤)并在代码中设置关系。

2)使用Dapper,因为我已经取得了更大的成功。我没有选择这个的原因是我的团队更熟悉EF。

有没有其他方法可以达到我使用EF所需的效果?

由于

1 个答案:

答案 0 :(得分:0)

可悲的是,我不得不在代码中手动构建对象关系。我确信有一种方法可以减轻痛苦,希望有人可以为此付出代价。

var personItemDict = new Dictionary<string, Item>();
var persons = context.Persons.Where(<condition>).ToDictionary(k=>k.Id, v=>v);
var orders = context.Orders.Where(<condition>).ToDictionary(k=>k.OrderId, v=>v);
var items = context.Items.Where(condition).ToList();

foreach(var item in items)
{
    item.Order = orders[item.OrderId];
    item.Order.Person = persons[item.Order.PersonId];

    // Add to dictionary
    if(false == personItemDict.ContainsKey(item.Order.Person.Name))
    {
        personItemDict.Add(
             item.Order.Person.Name,
             new List<Items>());
    }

    personItemDict[item.Order.Person.Name].Add(item);
}