Во-первых, я думаю, что это несколько смешно делать, но другие члены моей команды настаивают на этом, и я не могу придумать хороший аргумент против него, кроме "Я думаю, что это глупо"...
То, что мы пытаемся сделать, - создать полностью абстрактный слой данных, а затем выполнить различные реализации этого слоя данных. Достаточно просто, не так ли? Введите Entity Framework 4.1...
Наша конечная цель заключается в том, что программисты (я стараюсь оставаться только на слое данных) никогда не хотят, чтобы их подвергали конкретным классам. Они только когда-либо захотят использовать интерфейсы в своем коде, кроме того, что явно необходимо создать экземпляр factory.
Я хочу добиться чего-то вроде следующего:
Сначала у нас есть наша "общая" библиотека всех интерфейсов, мы будем называть ее "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()
{
...
}
}
}
Factory:
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; }
}
}
Context:
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 не может работать с интерфейсами и один ответ, говоря, что вы не можете реализовать IDbSet
(который я найти любопытных, почему бы им это предоставить, если вы не смогли его реализовать?), но до сих пор безрезультатно.
Заранее благодарим за помощь! J