我花了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所需的效果?
由于
答案 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);
}