【发布时间】:2011-11-17 21:46:03
【问题描述】:
首先,我认为这样做有些荒谬,但我团队的其他成员坚持这样做,除了“我认为这很愚蠢”之外,我无法提出很好的论据......
我们要做的是创建一个完全抽象的数据层,然后对该数据层进行各种实现。很简单,对吧?进入Entity Framework 4.1...
我们的最终目标是程序员(我尽我所能只停留在数据层)永远不想接触具体的类。除了显然需要实例化工厂之外,他们只想在代码中使用接口。
我想实现以下目标:
首先,我们有所有接口的“通用”库,我们称之为“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<IUser> Users { get; set; } // OR IDbSet<IUser> OR [IDbSet implementation]?
}
public interface IEntityFactory
{
DbSet<IUser> Users { get; }
DbSet<IAccount> 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<User>
{
public Configuration() : base()
{
...
}
}
}
internal class Account : IAccount
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DbSet<IUser> Users { get; set; } // OR IDbSet<IUser> OR [IDbSet implementation]?
public class Configuration : EntityTypeConfiguration<Account>
{
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<IUser> Users // OR IDbSet<IUser> OR [IDbSet implementation]?
{
get { return dataContext.Users; }
}
public DbSet<IAccount> Accounts // OR IDbSet<IUser> OR [IDbSet implementation]?
{
get { return dataContext.Accounts; }
}
}
上下文:
public class MyEfDataContext : DbContext
{
public MyEfDataContext(string connectionString)
: base(connectionString)
{
Database.SetInitializer<MyEfDataContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new User.Configuration());
modelBuilder.Configurations.Add(new Account.Configuration());
base.OnModelCreating(modelBuilder);
}
public DbSet<User> Users { get; set; }
public DbSet<Account> 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 无法使用接口的文章,one reply 说你不能实现IDbSet(我觉得有点奇怪,如果你能,他们为什么要提供它'不实现它?)但到目前为止无济于事。
提前感谢您的帮助! J
【问题讨论】:
-
顺便说一句。
IDbSet在单元测试中被暴露用于模拟,但模拟 EF 是另一个 hard task。
标签: c# design-patterns architecture entity-framework-4.1 abstraction