Imm*_*bat 6 .net c# inheritance entity-framework repository-pattern
我对存储库设计模式很陌生,在尝试实现它时,我已经达到了死胡同,关于继承.
即使我开始朝着正确的方向前进,我也不确定.
所以基本上我将有一个抽象的基类Product,例如id和imagePath,并且将有几个继承自此的产品.
namespace Common
{
public abstract class Product
{
public int Id { get; set; }
public string ImgPath { get; set; }
}
public class Scale : Product
{
public int AdditionalProperty { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
现在存储库如下:
public class BaseRepository
{
protected TEstEntities1 _dataContext = new TEstEntities1();
public BaseRepository()
{
_dataContext = new TEstEntities1();
}
}
public interface IProductRepository
{
Common.Product Get(int id);
void Add(Common.Product p);
void Update(Common.Product p);
List<Common.Product> ListAll();
}
public class ProductRepository : BaseRepository, IProductRepository
{
public Common.Product Get(int id)
{
throw new NotImplementedException();
}
public void Add(Common.Product p)
{
throw new NotImplementedException();
}
public void Update(Common.Product p)
{
throw new NotImplementedException();
}
public List<Common.Product> ListAll()
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题如下:我如何整合有关Scale的操作?将添加(Common.Scale s)之类的东西添加到IProductRepository似乎是一个坏主意.在Add(Common.Product p)里面看到我尝试添加哪种类型的产品,然后转换为它,然后添加,这似乎是一个坏主意.
我想如果我要更彻底地描述这个问题,我想重复尽可能少的代码,以某种方式隔离产品库中的基本产品添加/删除代码,并以某种方式将例如Scale特定代码添加到另一个内部类或方法.
我的一个更彻底的方法就是这个:
public interface IProductRepository<T> where T : Common.Product
{
T Get(int id);
void Add(T p);
void Delete(T p);
}
public abstract class ProductRepository : BaseRepository
{
protected void Add(Common.Product p)
{
_dataContext.AddToProduct(new Product { Id = p.Id, Image = p.ImgPath });
_dataContext.AcceptAllChanges();
}
protected void Delete(Common.Product p)
{
var c = _dataContext.Product.Where(x => x.Id == p.Id).FirstOrDefault();
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
}
protected Product Get(int id)
{
return _dataContext.Product.Where(x => x.Id == id).FirstOrDefault();
}
}
public class CantarRepository : ProductRepository, IProductRepository<Common.Scale>
{
public void Add(Common.Scale p)
{
base.Add(p);
_dataContext.Scale.AddObject
(new Scale { ProductId = p.Id, AdditionalProperty = p.AdditionalProperty });
_dataContext.AcceptAllChanges();
}
public void Delete(Common.Scale p)
{
var c = _dataContext.Scale.Where(x => x.ProductId == p.Id);
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
base.Delete(p);
}
public new Common.Scale Get(int id)
{
var p = base.Get(id);
return new Common.Scale
{
Id = p.Id,
ImgPath = p.Image,
AdditionalProperty = _dataContext.Scale.Where
(c => c.ProductId == id).FirstOrDefault().AdditionalProperty
};
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这有一个原因.如果我使用工厂模式返回IProductRepository并在其中使用IProductRepository进行实例化,由于协方差和逆变,这将无法工作,并且IProductRepository不能同时具有逆变和协变性,并且将方法拆分为两个接口似乎违反直觉而且很麻烦.
我怀疑我需要工厂模式才能返回基类接口,但我也愿意接受这方面的建议.正如我所说,我对回购模式非常新手.
我很好奇我做错了什么,我怎么能解决这个问题,以及如何更好地实现这一点.
谢谢.
我最近实施了这样的事情。ProductRepository(使用您的示例类型名称)我有一个知道如何保留/取消保留所有子类型的单个Product。
最终,您的支持数据存储必须能够存储各种子类型及其引入的任何属性。您的存储库类型还必须知道如何利用每个给定子类型的这些功能。因此,每次添加子类型时,您都将涉及一些工作,例如,将表列添加到支持数据存储以保存它可能引入的属性。这意味着您还需要对存储库类型进行适当的更改。因此,在传递给存储库类型时检查实体的类型似乎是最简单的,如果它不是受支持的类型,则抛出异常,因为存储库无法对其执行任何其他操作。类似地,当检索实体列表时,存储库必须知道如何检索每个实体子类型并构造一个实例。由于这些都源自Product,因此它们都可以形成IEnumerable<Product>返回值。