当前位置: 首页 > 编程语言 > C#

C#学习教程:.net中的存储库模式和继承分享

时间:2023-04-11 10:52:41 C#

.net中的存储库模式和继承我对存储库设计模式非常陌生,在尝试实现它时,我在继承方面遇到了死胡同。即使我开始朝着正确的方向前进,我也不确定。所以基本上我会有一个抽象基类Product,比如id和imagePath,并且会有几个Products继承自这个。命名空间Common{publicabstractclassProduct{publicintId{get;放;}公共字符串ImgPath{得到;放;}}publicclassScale:Product{publicintAdditionalProperty{get;类BaseRepository{protectedTEstEntities1_dataContext=newTEstEntities1();publicBaseRepository(){_dataContext=newTEstEntities1();}}publicinterfaceIProductRepository{Common.ProductGet(intid);voidAdd(Common.Productp);voidUpdate(Common.Productp);列出ListAll();}publicclassProductRepository:BaseRepository,IProductRepository{publicCommon.ProductGet(intid){thrownewNotImplementedException();}publicvoidAdd(Common.Productp){thrownewNotImplementedException();}publicvoidUpdate(Common.Productp){thrownewNotImplementedException();}publicListListAll(){thrownewNotImplementedException();我的问题如下:HowdoIintegrateoperationsonScale?向IProductRepository添加类似add(Common.Scales)的内容似乎不是一个好主意。在Add(Common.Productp)中查看我要添加的产品类型,然后转换为它,然后添加,这似乎是个坏主意。我想如果我要更彻底地描述问题,我想重复尽可能少的代码,以某种方式隔离产品库中的基本产品添加/删除代码,并以某种方式添加例如将特定代码扩展到另一个内部类或方法。我的一个更彻底的方法就是这个:publicinterfaceIProductRepositorywhereT:Common.Product{TGet(intid);无效添加(Tp);无效删除(Tp);}publicabstractclassProductRepository:BaseRepository{protectedvoidAdd(Common.Productp){_dataContext.AddToProduct(newProduct{Id=p.Id,Image=p.ImgPath});_dataContext.AcceptAllChanges();}protectedvoidDelete(Common.Productp){varc=_dataContext.Product.Where(x=>x.Id==p.Id).FirstOrDefault();_dataContext.DeleteObject(c);_dataContext.AcceptAllChanges();}protectedProductGet(intid){return_dataContext.Product.Where(x=>x.Id==id).FirstOrDefault();}}publicclassCantarRepository:ProductRepository,IProductRepository{publicvoidAdd(Common.Scalep){base.Add(p);_dataContext.Scale.AddObject(newScale{ProductId=p.Id,AdditionalProperty=p.AdditionalProperty});_dataContext.AcceptAllChanges();}publicvoidDelete(Common.Scalep){varc=_dataContext.Scale.Where(x=>x.ProductId==p.Id);_dataContext.DeleteObject(c);_dataContext.AcceptAllChanges();基础.删除(p);}publicnewCommon.ScaleGet(intid){varp=base.Get(id);returnnewCommon.Scale{Id=p.Id,ImgPath=p.Image,AdditionalProperty=_dataContext.Scale.Where(c=>c.ProductId==id).FirstOrDefault().AdditionalProperty};不幸的是,这是有原因的如果我使用工厂模式返回IProductRepository并在其中使用IProductRepository实例化它,由于协变和逆变,这将不起作用,并且IProductRepository不能同时逆变和协变,并且拆分为两个接口的方法似乎违反直觉且麻烦。我怀疑我需要工厂模式来返回基类接口,但我也愿意接受有关这方面的建议。正如我所说,我对回购架构非常陌生。我很好奇我做错了什么,我该如何解决这个问题,以及如何更好地实现这一点。谢谢。您错误地使用了继承。如果重要的区别是附加属性,则不能将Scale视为(是一个)Product-这使得Scale的公开接口与Product不同,此时继承只会妨碍您。使用继承来共享行为,而不是属性。继承试图解决什么问题?我想重复尽可能少的代码以便在没有一点重复的情况下完成工作,而不是尝试使用令人难以置信的设计?此外,这是您与继承共享的所有内容:publicintId{get;放;}公共字符串ImgPath{得到;放;复制两个自动实现的属性的定义很难算作重复,这当然不是一个值得关注的问题。然而,滥用继承是相当严重的。下一个维护你的应用程序的人会诅咒你。所以基本上我会有一个抽象基类Product,比如id和imagePath,并且会有几个Products继承自这个。那么当您添加新类型的产品时,您将不得不扩展继承层次结构吗?这似乎是个坏主意。我不是通用存储库的忠实粉丝,但看到你的代码后我认为你应该使用它:publicinterfaceIEntity{intId{get;}}publicinterfaceIRepositorywhereT:class,IEntity{IQueryableGetQuery();TGet(intid);无效添加(T实体);无效更新(T实体);voidDelete(T实体);}执行:publicRepositorywhereT:class,IEntity{privateObjectSet_set;//或DbSetprivateObjectContext_context;//或DbContextpublicRepository(ObjectContextcontext)//或DbContext{_context=context;_set=context.CreateObjectSet();//_context.Set()forDbContext}publicIQueryableGetQuery(){return_set;}publicTGet(intid){return_set.SingleOrDefault(e=>e.Id==id);}publicvoidAdd(Tentity){_set.AddObject(entity);}publicvoidUpdate(Tentity){_set.Attach(entity);context.ObjectStateManager.ChangeObjectState(entity,EntityState.Modified);//或者context.Entry(entity).State=EntityState.Modified;对于DbContext}publicvoidDelete(entity){_set.Attach(entity);_set.删除对象(实体);}}没有AcceptAllChanges因为它会重置ObjectStateManager并且永远不会保存您的更改没有重建对象因为它没有意义。使用这个存储库非常简单:varrepo=newBaseRepository(context);repo.Add(新产品(){...});repo.Add(newScale(){...});//是的,这是有效的,因为派生实体由相同的集合处理context.Save();我最近实施了这样的事情。(使用您的示例类型名称)我有一个ProductRepository,它知道如何持久化/取消持久化所有Product子类型。最终,您的后备数据存储必须能够存储各种子类型及其引入的任何属性。您的存储库类型还必须知道如何为每个给定的子类型利用这些功能。因此,每次添加子类型时,都会涉及一些工作,例如,将表列添加到后备数据存储以保存它可能引入的属性。这意味着您还需要对存储库类型进行适当的更改。因此,最简单的方法是在传递给您的存储库类型时检查实体的类型,如果它不是受支持的类型则抛出异常,因为您的存储库无法使用它。同样,在检索实体列表时,存储库必须知道如何检索每个实体子类型并构造一个实例。由于这些都来自Product,所以它们都可以在IEnumerable返回值中形成项目。以上就是《C#学习教程:RepositoryModeandInheritancein.Net》分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢