实体框架和存储库模式概念上的困难
我正在使用ASP.NET MVC和SQL Server 2012制作一个Intranet网站。我正在使用洋葱体系结构进行存储库和架构设计。我的问题是,我所在的公司已经有几个服务器数据库,其中表格之间没有任何关系。相反,有表格来映射这些关系。例如,一个表User和一个Document Document有一个表User_joint_Document来创建一个关系,包含两个ID(IDDocument和IDUser)。现在,当我写我的通用仓库:实体框架和存储库模式概念上的困难
class Repository<T> : IRepository<T> where T : class
问题是通用类型T是没有意义的,并使用EF查询,这是正常的,我不能影响我的模型值,什么将是巨大的。将有一个父类BaseEntity来为每个表定义的ID,那么我可以这样写:
class Repository<T> : IRepository<T> where T : BaseEntity
和我所有的表款会从BaseEntity继承。但这也意味着以关系方式重写整个数据库并手动映射每个数据库POCO(如果我错了,请纠正我),并且我没有技能来做到这一点(不同服务器数据库中有超过300个表而且我没有适当的知识和经验来做这种手术)。
有没有办法让我的原始数据库结构,仍然写一个通用储存库?如何去做这件事?
编辑澄清我的问题,因为@saeb部分回答我的问题。我可以有一个通用的回购没有我的数据库POCO父级?或者我需要它以便只有一个存储库来统治它们?例如:
class Repository<T>:IRepository<T> where T : class
{
private readonly ApplicationContext context;
private DbSet<T> entities;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
}
public T Get(long id)
{
return entities.SingleOrDefault(s => s.IDUser == id);
//This does not work, IDUser isn't recognized
}
感谢您的帮助!
...在该表具有相互之间没有关系的几个服务器的DB ...
但他们做有关系,一个Many-to-Many关系,这是通过该定义第三映射表(无论这是一个正确定义关系是另一个话题)
...问题是通用类型T是没有意义的,我不能影响我的模型中使用EF查询的值...
为什么不是这样,为什么你不能?考虑你的表的例子,你有两个实体,User
和Document
,他们会是这样的:
public class User
{
public int IDUser { get; set; }
public virtual ICollection<Document> Documents { get; set; }
...
}
public class Document
{
public int IDDocument { get; set; }
public virtual ICollection<User> Users { get; set; }
...
}
而且你可以使用流利的API您的上下文的OnModelCreating
建立通过第三表的关系:
public class YourContext: DbContext
{
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany<Document>(u => u.Documents)
.WithMany(d => d.Users)
.Map(userJointDocument =>
{
userJointDocument.MapLeftKey("IDUser");
userJointDocument.MapRightKey("IDDocument");
userJointDocument.ToTable("User_joint_Document");
});
}
...
}
然后,如果它们之间有直接的关系,你可以查询在你的仓库User
S和Document
S作为你会的。 Here是more好sources了解更多关于这个,如果你喜欢。
感谢您的确切答案和良好的文档。我已经这样做了,但是我的回购仍然存在问题,我无法识别这些ID。我编辑了我的问题,以显示我的回购看起来像 –
不能标记你很奇怪 –
至于我能看到你的问题,现在有实现这一目标没有把至少一个基类或您的实体的接口/波苏斯
你可以玩弄的表达式实现一个通用的存储库的方式
public interface IEntity<T> where T : class
{
Expression<Func<T, bool>> GetByIdPredicate(long id);
}
public partial class User : IEntity<User>
{
public int UserID { get; set; }
public Expression<Func<User, bool>> GetByIdPredicate(long id)
{
return (User entity) => entity.UserID == id;
}
}
class Repository<T>:IRepository<T> where T : class, IEntity, new()
{
private readonly ApplicationContext context;
private DbSet<T> entities;
T dummyEntity;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
dummyEntity = new T();
}
public T Get(long id)
{
return entities.SingleOrDefault(dummyEntity.GetByIdPredicate(id));
}
有可能也摆脱了dummyEntity
场
哦,这是一个非常有趣的事情。我实际上重新形成了我的问题,并在这里有另一个答案,如果你有兴趣,它都使用Expression方法打包在一个方法中:https://stackoverflow.com/questions/44591796/does-a-generic-repository-需要-A-基实体类待施加-到处/ 44592318#44592318 –
你给Users'的'和'Documents'在数据库中正确的实例的更清洁的方式。一个用户可以有许多文档,所以你需要一个'User_joint_Document'联结表。这正是应该如何构建关系数据库的结构。 – melkisadek
但是,如果您使用的是洋葱体系结构,则会自动为您创建存储库,您只需在DataOnion中注册它们即可。 –
@melkisadek Bah!这就是我在DB上工作的糟糕之处。我会认为你会在两张桌子之间有类似1-1的关系或者类似的东西?也许那个rel'ship是一个真正的桌子?真的不是我强大的一面。如果我用ID创建父类,那么关系表会变成什么?由于它有IDDocument和IDUser,但现在我只能从父类 –