我正在使用一个简单的EF / MVC应用程序,我正在尝试实现一些存储库来处理我的实体。我已经设置了一个BaseObject类和一个IBaseRepository接口来处理最基本的操作,所以我不必每次都重复自己:
public abstract class BaseObject<T>
{
public XA.Model.Entities.XAEntities db;
public BaseObject()
{
db = new Entities.XAEntities();
}
public BaseObject(Entities.XAEntities cont)
{
db = cont;
}
public void Delete(T entity)
{
db.DeleteObject(entity);
db.SaveChanges();
}
public void Update(T entity)
{
db.AcceptAllChanges();
db.SaveChanges();
}
}
public interface IBaseRepository<T>
{
void Add(T entity);
T GetById(int id);
IQueryable<T> GetAll();
}
但后来我发现自己必须在每个存储库中实现3种基本方法(Add,GetById&amp; GetAll):
public class AgencyRepository : Framework.BaseObject<Agency>, Framework.IBaseRepository<Agency>
{
public void Add(Agency entity)
{
db.Companies.AddObject(entity);
db.SaveChanges();
}
public Agency GetById(int id)
{
return db.Companies.OfType<Agency>().FirstOrDefault(x => x.Id == id);
}
public IQueryable<Agency> GetAll()
{
var agn = from a in db.Companies.OfType<Agency>()
select a;
return agn;
}
}
如何将这些内容放入我的BaseObject类中,这样我就不会与DRY冲突。
答案 0 :(得分:1)
您好我遇到了同样的问题。请按照这样的解决方案
namespace ABC
{
public class EntitiesRepository<T> : IDisposable where T : class
{
private ObjectContext _context;
/// <summary>
/// The IObjectSet that represents the current entity.
/// </summary>
private ObjectSet<T> _objectSet;
public OperationStatus status { get; set; }
/// <summary>
/// Initializes a new instance of the DataRepository class
/// </summary>
public BilderQuizEntitiesRepository()
{
_context = new Entities(); //DBContext
_objectSet = _context.CreateObjectSet<T>();
}
public T Select(int id)
{
EntityKey key = GetEntityKey(id);
return (T)_context.GetObjectByKey(key);
}
public void Delete(T entity)
{
try
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
EntityKey key = GetEntitySpecificKey(entity);
T attachEntity = (T)_context.GetObjectByKey(key);
_objectSet.DeleteObject(attachEntity);
SaveChanges();
}
catch
{
}
}
public void Delete(int id)
{
EntityKey key = GetEntityKey(id);
Delete((T)_context.GetObjectByKey(key));
SaveChanges();
}
public void Update(T entity)
{
try
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
EntityKey key = GetEntitySpecificKey(entity);
T attachEntity = (T)_context.GetObjectByKey(key);
_objectSet.Attach(attachEntity);
_objectSet.ApplyCurrentValues(entity);
SaveChanges();
}
catch
{
}
}
/// <summary>
/// Returns Entity Key
/// </summary>
/// <param name="keyValue"></param>
/// <returns></returns>
private EntityKey GetEntityKey(object keyValue) //Get EnrityKey
{
var entitySetName = _context.DefaultContainerName + "." + _objectSet.EntitySet.Name;
var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
return entityKey;
}
/// <summary>
/// Returns Entity Key
/// </summary>
/// <param name="keyValue"></param>
/// <returns></returns>
private EntityKey GetEntitySpecificKey(T entity) //Get EnrityKey
{
Type objType = typeof(T);
var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
var pi = objType.GetProperty(keyPropertyName);
var keyValue = pi.GetValue(entity, null);
var entitySetName = _context.DefaultContainerName + "." + _objectSet.EntitySet.Name;
var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
return entityKey;
}
private string GetPrimaryKeyValue(T entity)
{
Type objType = typeof(T);
var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
var pi = objType.GetProperty(keyPropertyName);
var keyValue = pi.GetValue(entity, null);
return keyValue.ToString();
}
/// <summary>
/// Saves all context changes
/// </summary>
public bool SaveChanges()
{
return _context.SaveChanges() > 0 ? true : false;
}
/// <summary>
/// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
/// </summary>
/// <param name="disposing">A boolean value indicating whether or not to dispose managed resources</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
}
}
如果你找到了更好的方法,请告诉我。
答案 1 :(得分:0)
除非您的基类能够实现该接口(然后您可以继承它的实现),否则您每次都会陷入困境。如果每个孩子的步骤不同,那么你不要重复自己,即使它有点像。
作为一个偏离主题的评论,不是在你的基础构造函数中创建db对象,而是可以为自己节省一些痛苦,而依赖注入它。如果您在其中放置任何值得测试的代码,它将使您的存储库更容易进行单元测试。
答案 2 :(得分:0)
您可以使用EF 4中的T4轻松完成此操作。通过更多工作,您可以使用EF 1中的T4进行此操作。
但我建议你不要。 MyEntity.Update()
将是一部小说。 EF不允许您将部分更改保存到上下文(如一个特定对象)。所以你的方法会做一些与它看起来完全不同的事情。恕我直言,这个设计正在对抗EF。它还可以通过设计使您的实体具有持久性感知能力。
答案 3 :(得分:0)
这是一个老问题,但它仍然是开放的,所以也许对某人有帮助。我对这种情况的解决方案是使用一个abstrat类,其泛型类型实现了select,insert,update或delete等基本操作。
我的基类看起来像这样:
public abstract class MyContext<T, key> : IDisposable where T : class {
private DbEntities db; //my database context
private DbSet<T> entities; //specific set
protected MyContext(DbEntities db) {
entities = db.Set<T>();
this.db = db;
}
public T Add(T entity) {
entities.Add(entity);
db.SaveChanges();
return entity;
}
public T Get(key id) {
return entities.Find(id);
}
public List<T> GetAll() {
return entities.ToList();
}
public void Delete(key id) {
T objectToDelete=entities.Find(id);
if(objectToDelete!=null){
entities.Remove(objectToDelete);
db.SaveChanges();
}
}
public void Delete(T entity) {
entities.Remove(entity);
db.SaveChanges();
}
public void Delete(List<T> items) {
foreach (T entity in items) {
entities.Remove(entity);
}
db.SaveChanges();
}
public void Update(T entity) {
entities.Attach(entity);
db.Entry(entity).State = EntityState.Modified;
db.SaveChanges();
}
public abstract void Dispose();
}
具体示例类
public class PermissionDataBase : MyContext<Permission,int>{
//Mapped class Permission where the key is int
private DbEntities db=null;
public PermissionDataBase(DbEntities db):base(db) {
this.db = db;
}
//Additional methods (if required)
public Permission FindByName(string name) {
return db.Permissions.FirstOrDefault(p => p.Name == name);
}
public override void Dispose() {
db.Dispose();
}
}
测试
public class ModelsTest {
[TestMethod]
public void TestMethod1() {
DbEntities db = new DbEntities();
using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
Permission newEntity = new Permission() {
Name = "Test1"
};
permissionDb.Add(newEntity);
Assert.IsTrue(newEntity.Id > 0);
}
}
[TestMethod]
public void TestMethod2() {
DbEntities db = new DbEntities();
using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
List<Permission> items = permissionDb.GetAll();
Assert.IsTrue(items.Count > 0);
}
}
[TestMethod]
public void TestMethod3() {
DbEntities db = new DbEntities();
using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
Permission toDelete = permissionDb.Get(3); //Assuming id=3 exists
permissionDb.Delete(toDelete);
Permission deleted = permissionDb.Get(3);
Assert.IsNull(deleted);
}
}
}
此代码适用于Visual Studio Community 2013中的Entity Framework 5.