以下是使用EF6实现存储库模式。我想以下列方式使用通用存储库,从而无需为每种类型
创建存储库_unitOfWork.Repository(entityName).Insert(entityName)
public interface IRepository<T> where T : class
{
//--Search Operations
IEnumerable<T> Get();
T GetByID(object id);
void Insert(T entity);
void Delete(object id);
void Delete(T entityToDelete);
void Update(T entityToUpdate);
}
我创建了一个所有实体都将继承的基类。这个基类的意图是我可以用这个基类引用所有实体。
public class IRepositoryEntity
{
}
以下是Entity Framework生成的代码,我从IRepositoryEntity
public partial class Client_Entity: IRepositoryEntity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Client_Entity()
{
}
public int Id { get; set; }
}
以下是通用存储库
public class GenericRepository<IRepositoryEntity> : IRepository<IRepositoryEntity> where IRepositoryEntity : class
{
#region Private member variables...
internal ConsularDB_March2016Entities Context;
internal DbSet<IRepositoryEntity> DbSet;
#endregion
#region Public Constructor...
/// <summary>
/// Public Constructor,initializes privately declared local variables.
/// </summary>
/// <param name="context"></param>
public GenericRepository(ConsularDB_March2016Entities context)
{
this.Context = context;
this.DbSet = context.Set<IRepositoryEntity>();
}
///// <summary>
///// Public Constructor,initializes privately declared local variables.
///// </summary>
///// <param name="context"></param>
//public GenericRepository()
//{
// this.Context = context;
// this.DbSet = context.Set<IRepositoryEntity>();
//}
#endregion
#region Public member methods...
/// <summary>
/// generic Get method for Entities
/// </summary>
/// <returns></returns>
public IEnumerable<IRepositoryEntity> Get()
{
IQueryable<IRepositoryEntity> query = DbSet;
return query.ToList();
}
}
以下是IUnitOfWork
界面及其实现
public interface IUnitOfWork
{
#region Properties
GenericRepository<Client_Entity> ClientRepository { get; }
#endregion
#region Public methods
/// <summary>
/// Save method.
/// </summary>
void Save();
GenericRepository<IRepositoryEntity> Repository(IRepositoryEntity entity);
#endregion
}
/// <summary>
/// Unit of Work class responsible for DB transactions
/// </summary>
public class UnitOfWork : IDisposable, IUnitOfWork
{
#region Private member variables...
private March2016Entities _context = null;
private GenericRepository<Client_Entity> _clientRepository;
#endregion
public UnitOfWork()
{
_context = new March2016Entities();
}
#region Public member methods...
/// <summary>
/// Save method.
/// </summary>
public void Save()
{
try
{
_context.Configuration.ValidateOnSaveEnabled = false;
_context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
var context = ((IObjectContextAdapter)_context).ObjectContext;
var refreshobjects = _context.ChangeTracker.Entries().Select(c => c.Entity).ToList();
context.Refresh(System.Data.Entity.Core.Objects.RefreshMode.StoreWins, refreshobjects);
_context.SaveChanges();
}
catch (DbEntityValidationException e)
{
var outputLines = new List<string>();
foreach (var eve in e.EntityValidationErrors)
{
outputLines.Add(string.Format("{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State));
foreach (var ve in eve.ValidationErrors)
{
outputLines.Add(string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
}
}
System.IO.File.AppendAllLines(@"C:\errors.txt", outputLines);
throw e;
}
}
#endregion
#region Implementing IDiosposable...
#region private dispose variable declaration...
private bool disposed = false;
#endregion
/// <summary>
/// Protected Virtual Dispose method
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
Debug.WriteLine("UnitOfWork is being disposed");
_context.Dispose();
}
}
this.disposed = true;
}
/// <summary>
/// Dispose method
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region GenericMembers
Dictionary<string, GenericRepository<IRepositoryEntity>> repostories = new Dictionary<string, GenericRepository<IRepositoryEntity>>();
/// <summary>
/// Generic Repository method which checks the repository is available if not,
/// it sets it up.
/// </summary>
/// <param name="entity">Entity</param>
/// <returns>Repository to use.</returns>
public GenericRepository<IRepositoryEntity> Repository(IRepositoryEntity entity)
{
string index = entity.GetType().ToString();
if (!repostories.ContainsKey(index))
{
//Reflections to create the repoositiory if it is not needed.
Type type1 = typeof(GenericRepository<IRepositoryEntity>);
Type[] typeArgs = { entity.GetType() };
Type constructed = type1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(constructed, this._context);
//if (o is GenericRepository<IRepositoryEntity>)
//{
object genericRepo = (object)o;
var rep = (GenericRepository<IRepositoryEntity>)genericRepo;
//rep.Context = this._context;
repostories.Add(index, rep);
//}
}
return this.repostories[index];
}
#endregion
}
我正在尝试在以下函数中动态创建GenericRepository
列表
public GenericRepository<IRepositoryEntity> Repository(IRepositoryEntity entity)
在创建实例时,它抛出以下异常
mscorlib.dll中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理
附加信息:GenericRepository`1 [IRepositoryEntity]不是GenericTypeDefinition。 MakeGenericType只能在Type.IsGenericTypeDefinition为true的类型上调用。
我理解异常,但不确定如何更改实现,以便我能够实现所需的功能。另外,我如何将IRepositoryEntity
添加到EF模型中,因为它表示它不是模型的一部分。
public void ValidateGenericEntityInsert(IRepositoryEntity entityName)
{
IRepositoryEntity entity = (IRepositoryEntity)Activator.CreateInstance(entityName);
_unitOfWork.Repository(entityName).Insert(entityName);
// int generatedId = GetPropertyFromEntity(entity, en => en.Id);
int generatedId = (int)GetPropertyFromEntity(entityName, "Id");
Assert.That(generatedId, Is.GreaterThan(0));
}