我目前有一个完整的通用存储库,但我缺少一个功能,那就是使用
包括()和Find()
在一起。
所以现在我有:
public E FindById<E>(int id) where E : class
{
return DataContext.Set<E>().Find(id);
}
使用
调用var person = PersonRepo.FindById<Person>(personId);
我想要有类似的东西:
var person = PersonRepo.FindByIdWithIncludes<Person>(personId,new[]{"State.Address"});
所以,沿着这条路线(这只是一个测试):
public E FindByIdWithIncludes<E>(int id, string[] includes) where E : class
{
var entitySet = DataContext.Set<E>();
DbQuery<E> entityQuery;
foreach (var include in includes)
{
entityQuery = entitySet.Include(include);
}
return entityQuery.Find(id); //this is were it breaks
}
有可能吗?
答案 0 :(得分:7)
您无法直接使用Find
- Find
无法使用包含。您必须使用SingleOrDefault
。
首先,您需要为实体定义接口以公开其密钥。
public interface IEntityWithId
{
public int Id { get; set; }
}
接下来,您可以编写带约束的简单方法来访问密钥:
public E FindByIdWithIncludes<E>(int id, string[] includes)
where E : class, IEntityWithId
{
IQueryable<E> entityQuery = DataContext.Set<E>();
foreach (var include in includes)
{
entityQuery = entityQuery.Include(include);
}
return entityQuery.SingleOrDefault(e => e.Id == id);
}
顺便说一下。您可以使用强类型包含 - here is an example。
答案 1 :(得分:2)
你可以反过来使用Find
,但与Load
结合使用。在某些情况下,表现可能比Include-SingleOrDefault
更好,但这实际上取决于情景。
非通用示例:
private User GetByUID(int uID, bool includeDetails = false, bool includeAddresses = false)
{
var result = context.Users.Find(uID);
if (includeDetails)
{
// load user-details (1:1 relation)
context.Entry(result)
.Reference<UserDetails>(us => us.UserDetails)
.Load();
}
if (includeAddresses)
{
// load user-addresses (1:m relation)
context.Entry(result)
.Collection(us => us.Addresses)
.Load();
}
return result;
}
根据您的需要制作它是不应该的。