【问题标题】:Generic Repository & Entity Framework Logic to Retrieve Entity with Includes使用包含检索实体的通用存储库和实体框架逻辑
【发布时间】:2012-08-14 08:13:09
【问题描述】:

我有两个 Entity Framework 5Get() 方法,它们执行 (i) 通过 ID 获取单个实体,以及 (ii) 通过过滤器获取单个实体用螺栓固定任何急切的负载。代码见下:

internal readonly FallenNovaContext Context;
private readonly DbSet<TEntity> _dbSet;

internal GenericRepository(FallenNovaContext context)
{
    Context = context;
    _dbSet = context.Set<TEntity>();
}

// (i) Get by ID.
public TEntity GetById(int id)
{
    return _dbSet.Find(id);
}

// (ii) Get by filter and optional eager loading includes.
public TEntity Get(
    Expression<Func<TEntity, bool>> filter = null,
    IEnumerable<string> includePaths = null)
{
    IQueryable<TEntity> query = _dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    if (includePaths != null)
    {
        query = includePaths.Aggregate(query, (current, includePath) => current.Include(includePath));
    }

    return query.SingleOrDefault();
}

现在所有这些都可以正常工作随着我的应用程序的增长我发现我正在编写许多需要两者混合的非泛型方法 - 更具体地说,我想要一个通过 ID 获取的泛型方法,并且还能够急切加载相关实体。

所以方法签名看起来像这样:

 public TEntity GetById(
     int id,
     IEnumerable<string> includePaths)
 {
       // ???
 }

我可以这样称呼:

 User user = UnitOfWork.UserRepository.GetById(117, new List<string>() { "UserRole", "UserStatus" });

或者像这样:

 Car car = UnitOfWork.CarRepository.GetById(51, new List<string>() { "Make", "Model", "Tyres" });

任何有关我如何使用 Entity Framework 5 为 TEntity GetById(int id, IEnumerable includePaths) 方法的逻辑编码的建议的帮助将不胜感激。

【问题讨论】:

    标签: c# entity-framework-5


    【解决方案1】:

    首先,为实体编写一个基类,它定义了主键字段。像下面这样的东西可能会起作用:

    public abstract class BaseEntity
    {
        public int Id {get;set;}
    }
    

    然后,为您的存储库编写一个基类;在此基础存储库中定义所有通用方法。让这个存储库有一个实体类型的通用参数:

    public class RepositoryBase<TEntity> where TEntity : BaseEntity
    {
       public TEntity GetById(
         int id,
         params Expression<Func<TEntity, object>>[] includeList)
         {
                TEntity entity = null;
                ObjectQuery<TEntity> itemWithIncludes = context.Set<TEntity>() as ObjectQuery<TEntity>;
                foreach (Expression<Func<TEntity, object>> path in includeList)
                {
                    itemWithIncludes = ((IQueryable)itemWithIncludes.Include(path)) as ObjectQuery<T>;
                }
    
                IQueryable<TEntity> items = itemWithIncludes.AsQueryable<TEntity>();
                entity = items.Where(p => p.Id == id).SingleOrDefault();
                return entity;
         }
    }
    

    更新:@Bern 询问除了声明基类之外,是否还有其他方法可以找到主键。以下问题涉及到这个问题。

    Entity Framework 4: How to find the primary key?

    Entity Framework code first. Find primary key

    另一方面,我不知道 EF 5 中是否还有其他方法。

    【讨论】:

    • 谢谢@daryal - 2个问题“entityWithIncludes”在未声明时会做什么,除了您建议的方法之外,还有其他方法可以使用 EF5 获取主键吗?
    • entityWithIncludes 是一个错字,它是 itemWithIncludes;我在问题中修复了它。对于第二个问题,我将发布更新;但现在您可以通过更改 tt 文件来更改实体以继承基类。
    猜你喜欢
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多