用自定义DbSet / IDbSet包装DbSet ?
首先,我认为这样做有些荒谬,但是我团队的其他成员坚持认为,除了“我认为这是愚蠢的”之外,我无法提出反对它的好论据……
我们要做的是创建一个完全抽象的数据层,然后对该数据层进行各种实现。 很简单吧? 输入entity framework4.1 …
我们的最终目标是程序员(我尽我所能只留在数据层)永远不希望暴露在具体的类中。 除了显然需要实例化工厂之外,他们只想在代码中使用接口。
我希望实现以下内容:
首先我们有所有接口的“Common”库,我们称之为“Common.Data”:
public interface IEntity { int ID { get; set; } } public interface IUser : IEntity { int AccountID { get; set; } string Username { get; set; } string EmailAddress { get; set; } IAccount Account { get; set; } } public interface IAccount : IEntity { string FirstName { get; set; } string LastName { get; set; } DbSet Users { get; set; } // OR IDbSet OR [IDbSet implementation]? } public interface IEntityFactory { DbSet Users { get; } DbSet Accounts { get; } }
从那时我们有一个实现库,我们称之为“Something.Data.Imp”:
internal class User : IUser { public int ID { get; set; } public string Username { get; set; } public string EmailAddress { get; set; } public IAccount Account { get; set; } public class Configuration : EntityTypeConfiguration { public Configuration() : base() { ... } } } internal class Account : IAccount { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DbSet Users { get; set; } // OR IDbSet OR [IDbSet implementation]? public class Configuration : EntityTypeConfiguration { public Configuration() : base() { ... } } }
厂:
public class ImplEntityFactory : IEntityFactory { private ImplEntityFactory(string connectionString) { this.dataContext = new MyEfDbContext(connectionString); } private MyEfDbContext dataContext; public static ImplEntityFactory Instance(string connectionString) { if(ImplEntityFactory._instance == null) ImplEntityFactory._instance = new ImplEntityFactory(connectionString); return ImplEntityFactory._instance; } private static ImplEntityFactory _instance; public DbSet Users // OR IDbSet OR [IDbSet implementation]? { get { return dataContext.Users; } } public DbSet Accounts // OR IDbSet OR [IDbSet implementation]? { get { return dataContext.Accounts; } } }
语境:
public class MyEfDataContext : DbContext { public MyEfDataContext(string connectionString) : base(connectionString) { Database.SetInitializer(null); } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new User.Configuration()); modelBuilder.Configurations.Add(new Account.Configuration()); base.OnModelCreating(modelBuilder); } public DbSet Users { get; set; } public DbSet Accounts { get; set; } }
然后前端程序员将使用它,例如:
public class UsingIt { public static void Main(string[] args) { IEntityFactory factory = new ImplEntityFactory("SQLConnectionString"); IUser user = factory.Users.Find(5); IAccount usersAccount = user.Account; IAccount account = factory.Accounts.Find(3); Console.Write(account.Users.Count()); } }
所以这就是它……我希望这里的某个人能够指出我正确的方向,或者帮我解决一个可以反击开发团队的好论点。 我看过这个网站上的其他一些文章,关于EF无法使用接口和一个回复说你不能实现IDbSet
(我觉得有点好奇,为什么他们会提供它,如果你不能实现它?)但到目前为止无济于事。
在此先感谢您的帮助! Ĵ
第一个参数是EF不能与接口一起使用。 必须使用实体实现来定义DbSet
。
第二个参数是你的实体不应该包含DbSet
– 这是与上下文相关的类,你的实体应该是纯粹的依赖,除非你要实现Active记录模式。 即使在这种情况下,您也绝对无法访问另一个实体中不同实体的DbSet
。 即使你设置了set,你仍然太靠近EF,实体永远不会拥有访问另一个实体类型的所有实体的属性(不仅仅是那些与当前实例相关的实体)。
只是为了说清楚EF中的DbSet
有非常特殊的含义 – 它不是一个集合。 它是数据库的入口点(例如, DbSet
上的每个LINQ查询命中数据库),并且它在正常情况下不在实体上公开。
第三个参数是每个应用程序使用一个上下文 – 每个singleton工厂只有一个私有实例。 除非您正在进行一些单批运行批处理, 否则它肯定是错误的 。
最后一个论点很简单。 您需要付费才能提供function,而不是浪费时间进行抽象,这不会给您(和您的客户)带来任何商业价值。 它不是要certificate为什么你不应该创建这种抽象。 这是为了certificate你为什么要这样做。 使用它会得到什么价值? 如果你的同事无法提出具有商业价值的论据,你可以直接去你的产品经理并让他使用他的权力 – 他掌握了预算。
通常,抽象是精心设计的面向对象应用程序的一部分 – 这是正确的。 但:
什么时候进行“大量”抽象是有道理的?
如果您只使用目标应用程序(主要是按需提供单一用途的应用程序或外包解决方案),则只应在必要时使用抽象。 这些应用程序受成本驱动 – 目标是在最短的时间内以最低的成本提供工作解决方案。 即使在内部产生的应用程序不是很好,也必须实现这个目标 – 唯一重要的是应用程序是否符合要求。 基于“如果……发生了什么”或“可能我们将需要……”的任何抽象都会增加虚拟(非现有)需求的成本,这些需求将永远不会发生,并且在大多数情况下与客户的初始合同不计算在内这样的额外费用。
顺便说一句。 这种类型的应用程序是MS API和设计师策略的目标 – MS将使许多设计师和代码生成器创建非最佳但廉价和快速的解决方案,这些解决方案可以由技能较小且非常便宜的人创建。 最后一个例子是LightSwitch。
上述就是C#学习教程:用自定义DbSet / IDbSet包装DbSet ?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1033714.html