4

我目前有一个完整的通用存储库,但我缺少一个功能,那就是使用 Include()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
}

可能吗?

4

2 回答 2

9

您不能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); 
}

顺便提一句。您可以使用强类型包含 -这是一个示例

于 2012-07-26T08:22:53.080 回答
1

您也可以反过来使用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;
 }

使其符合您的需求应该不难。

于 2014-03-21T13:40:45.797 回答