目前我们使用的UnitOfWork设计模式是我们无法改变的。 通用存储库类如下所示:
public class Repository<T> : IDisposable, IRepository<T> where T : class
{
// Create our private properties
private readonly DbContext context;
private readonly DbSet<T> dbEntitySet;
/// <summary>
/// Default constructor
/// </summary>
/// <param name="context">The database context</param>
public Repository(DbContext context)
{
// If no context is supplied, throw an error
if (context == null)
throw new ArgumentNullException("context");
// Assign our context and entity set
this.context = context;
this.dbEntitySet = context.Set<T>();
}
/// <summary>
/// Allows the execution of stored procedures
/// </summary>
/// <typeparam name="T">The entity model</typeparam>
/// <param name="sql">The name of the stored procedure</param>
/// <param name="parameters">Option list of parameters</param>
/// <returns></returns>
public DbRawSqlQuery<T> SQLQuery(string sql, params object[] parameters)
{
return this.context.Database.SqlQuery<T>(sql, parameters);
}
/// <summary>
/// Gets all the entities
/// </summary>
/// <param name="includes">Option includes for eager loading</param>
/// <returns></returns>
public IQueryable<T> GetAll(params string[] includes)
{
IQueryable<T> query = this.dbEntitySet;
foreach (var include in includes)
query = query.Include(include);
return query;
}
/// <summary>
/// Creates an entity
/// </summary>
/// <param name="model"></param>
public void Create(T model)
{
this.dbEntitySet.Add(model);
}
/// <summary>
/// Updates an entity
/// </summary>
/// <param name="model"></param>
public void Update(T model)
{
this.context.Entry<T>(model).State = EntityState.Modified;
}
/// <summary>
/// Removes an entity
/// </summary>
/// <param name="model"></param>
public void Remove(T model)
{
this.context.Entry<T>(model).State = EntityState.Deleted;
}
/// <summary>
/// Dispose method
/// </summary>
public void Dispose()
{
this.context.Dispose();
}
,服务看起来像这样:
public class Service<T> where T : class
{
private readonly IUnitOfWork unitOfWork;
private readonly IRepository<T> repository;
protected IUnitOfWork UnitOfWork
{
get { return this.unitOfWork; }
}
protected IRepository<T> Repository
{
get { return this.repository; }
}
public Service(IUnitOfWork unitOfWork)
{
if (unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
this.unitOfWork = unitOfWork;
this.repository = unitOfWork.GetRepository<T>();
}
}
并且UnitOfWork类看起来像这样:
/// <summary>
/// Used to handle the saving of database changes
/// </summary>
/// <typeparam name="TContext"></typeparam>
public class UnitOfWork<TContext> : IUnitOfWork where TContext : DbContext, new()
{
// Private properties
private readonly DbContext context;
private Dictionary<Type, object> repositories;
// Public properties
public DbContext Context { get { return this.context; } }
/// <summary>
/// Default constructor
/// </summary>
public UnitOfWork()
{
this.context = new TContext();
repositories = new Dictionary<Type, object>();
}
/// <summary>
/// Gets the entity repository
/// </summary>
/// <typeparam name="TEntity">The entity model</typeparam>
/// <returns></returns>
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
// If our repositories have a matching repository, return it
if (repositories.Keys.Contains(typeof(TEntity)))
return repositories[typeof(TEntity)] as IRepository<TEntity>;
// Create a new repository for our entity
var repository = new Repository<TEntity>(context);
// Add to our list of repositories
repositories.Add(typeof(TEntity), repository);
// Return our repository
return repository;
}
/// <summary>
/// Saves the database changes asynchronously
/// </summary>
/// <returns></returns>
public async Task SaveChangesAsync()
{
try
{
// Save the changes to the database
await this.context.SaveChangesAsync();
// If there is an error
} catch (DbEntityValidationException ex) {
// Retrieve the error messages as a list of strings.
var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
this.context.Dispose();
}
}
现在我有一个 ProductService ,如下所示:
/// <summary>
/// Handles all product related methods
/// </summary>
public class ProductService : Service<Product>
{
/// <summary>
/// The default constructor
/// </summary>
/// <param name="unitOfWork"></param>
public ProductService(IUnitOfWork unitOfWork)
: base(unitOfWork)
{
}
/// <summary>
/// Gets all products
/// </summary>
/// <param name="includes">Optional eager loading includes</param>
/// <returns></returns>
public async Task<List<Product>> GetAllAsync(params string[] includes)
{
// Return as an asynchronous list
return await this.Repository.GetAll(includes).ToListAsync();
}
/// <summary>
/// Gets a single product by id
/// </summary>
/// <param name="id">The id of the product</param>
/// <param name="includes">Optional eager loading includes</param>
/// <returns></returns>
public async Task<Product> GetAsync(int id, params string[] includes)
{
var models = await this.GetAllAsync(includes);
return models.Where(model => model.Id == id).SingleOrDefault();
}
/// <summary>
/// Create a product
/// </summary>
/// <param name="model">The product model</param>
public void Create(Product model)
{
// Create a team
this.Repository.Create(model);
}
/// <summary>
/// Update a product
/// </summary>
/// <param name="model">The product model</param>
public void Update(Product model)
{
// Update a team
this.Repository.Update(model);
}
/// <summary>
/// Delete a product
/// </summary>
/// <param name="model">The product model</param>
public void Remove(Product model)
{
// Remove a team
this.Repository.Remove(model);
}
}
我已将Code First数据库设置为在删除产品时使用Cascading Delete。设置了相当多的1到1个表关系。如果我使用SQL Management Studio,我可以手动从数据库中删除产品,它将删除所有相关条目。 但是,如果我尝试从我的应用程序中删除它,我会收到此错误:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
理想情况下,我想循环遍历泛型类的子项(所以在 Reposity 类中)并检查是否为该实体启用了级联删除,如果是,我想删除它。 如果没有,什么都不做。
有没有人知道这是否可行或者知道另一个不涉及丢弃UnitOfWork设计模式的解决方案?