工作单元模式和更新实体集合属性
Unit of Work Pattern And Updating Entity Collection Properties
我正在为我的项目使用带有工作单元实现的通用存储库模式。
最近遇到一个无法解决的问题。当我尝试更新实体的集合 属性(即:添加新的关联实体)并在我的 UoW 上调用更新(将其委托给存储库,显然是 EF)时,它不会保存到数据库中。
我的通用存储库:
public class GenericRepository<TEntity> where TEntity : class
{
internal MyDBContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(MyDBContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
internal virtual IQueryable<TEntity> BuildQuery(Expression<Func<TEntity,bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = dbSet.AsNoTracking();
foreach (var include in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
if (filter != null)
query = query.Where(filter);
if (orderBy != null)
return orderBy(query);
return query;
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = BuildQuery(filter, orderBy, includeProperties);
return query.ToList();
}
public virtual void Update(TEntity entity)
{
dbSet.Attach(entity);
context.Entry<TEntity>(entity).State = EntityState.Modified;
}
}
我的工作单元实施
public class UnitOfWork : IDisposable
{
//code removed for clarity
public GenericRepository<CorporateServiceCategory> ServiceCategories
{
get
{
if(this.serviceCategoryRepository == null)
{
serviceCategoryRepository = new GenericRepository<CorporateServiceCategory>(context);
}
return serviceCategoryRepository;
}
}
public void Commit()
{
context.SaveChanges();
}
}
我想做的是:
using(var unit = new UnitOfwork())
{
//unit.Companies is a generic repository instance for Company entities.
var company = unit.Companies.Get(filter: f => f.Id == 1).SingleOrDefault();
company.ServiceCategories.Add(new ServiceCategory {Name = "Demo"});
unit.Companies.Update(company);
//This is a call to context.SaveChanges();
unit.Commit();
}
我希望此代码创建一个新的 Company -> ServiceCategory 关联并向数据库添加一条记录。当我在没有工作单元但使用 DbContext 本身的情况下执行相同的操作时,它起作用了。
我的 UoW 和通用存储库实施有什么问题?
感谢SOfanatic的评论,问题已经解决
我更新了我的 GenericRepository 的 BuildQuery 方法以反映 SOfanatic 的建议并且它有效。
这是更新后的 BuildQuery 方法:
internal virtual IQueryable<TEntity> BuildQuery(Expression<Func<TEntity,bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = this.context.IsReadOnly ? dbSet.AsNoTracking() : dbSet;
foreach (var include in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
if (filter != null)
query = query.Where(filter);
if (orderBy != null)
return orderBy(query);
return query;
}
DbContext.IsReadOnly 是我添加到我的 DbContext 实现中的自定义 属性。这样,如果我想以一种 "read-only" 模式(仅选择)加载实体,我会禁用延迟加载、代理生成和更改跟踪,因此它会稍微提高 EF 性能。
我正在为我的项目使用带有工作单元实现的通用存储库模式。
最近遇到一个无法解决的问题。当我尝试更新实体的集合 属性(即:添加新的关联实体)并在我的 UoW 上调用更新(将其委托给存储库,显然是 EF)时,它不会保存到数据库中。
我的通用存储库:
public class GenericRepository<TEntity> where TEntity : class
{
internal MyDBContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(MyDBContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
internal virtual IQueryable<TEntity> BuildQuery(Expression<Func<TEntity,bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = dbSet.AsNoTracking();
foreach (var include in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
if (filter != null)
query = query.Where(filter);
if (orderBy != null)
return orderBy(query);
return query;
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = BuildQuery(filter, orderBy, includeProperties);
return query.ToList();
}
public virtual void Update(TEntity entity)
{
dbSet.Attach(entity);
context.Entry<TEntity>(entity).State = EntityState.Modified;
}
}
我的工作单元实施
public class UnitOfWork : IDisposable
{
//code removed for clarity
public GenericRepository<CorporateServiceCategory> ServiceCategories
{
get
{
if(this.serviceCategoryRepository == null)
{
serviceCategoryRepository = new GenericRepository<CorporateServiceCategory>(context);
}
return serviceCategoryRepository;
}
}
public void Commit()
{
context.SaveChanges();
}
}
我想做的是:
using(var unit = new UnitOfwork())
{
//unit.Companies is a generic repository instance for Company entities.
var company = unit.Companies.Get(filter: f => f.Id == 1).SingleOrDefault();
company.ServiceCategories.Add(new ServiceCategory {Name = "Demo"});
unit.Companies.Update(company);
//This is a call to context.SaveChanges();
unit.Commit();
}
我希望此代码创建一个新的 Company -> ServiceCategory 关联并向数据库添加一条记录。当我在没有工作单元但使用 DbContext 本身的情况下执行相同的操作时,它起作用了。
我的 UoW 和通用存储库实施有什么问题?
感谢SOfanatic的评论,问题已经解决
我更新了我的 GenericRepository 的 BuildQuery 方法以反映 SOfanatic 的建议并且它有效。
这是更新后的 BuildQuery 方法:
internal virtual IQueryable<TEntity> BuildQuery(Expression<Func<TEntity,bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = this.context.IsReadOnly ? dbSet.AsNoTracking() : dbSet;
foreach (var include in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
if (filter != null)
query = query.Where(filter);
if (orderBy != null)
return orderBy(query);
return query;
}
DbContext.IsReadOnly 是我添加到我的 DbContext 实现中的自定义 属性。这样,如果我想以一种 "read-only" 模式(仅选择)加载实体,我会禁用延迟加载、代理生成和更改跟踪,因此它会稍微提高 EF 性能。