Entity framework 如何访问具有复合键的表';t模型首先使用代码?
我有一个无法更改的现有数据库,但希望使用EF访问。对于90%的数据库,我已经能够让代码优先EF工作,我印象非常深刻 我遇到了一个案例,我想知道如何通过导航属性建模或访问数据 在一种情况下,表是这样的(这个例子完全是虚构的,但代表了问题): 在表“品种”中,组织表示已定义品种的组织。一只狗可以有几个品种,但程序只显示一个,结果由组织id“过滤”——这是程序设置时配置的值 可能存在的数据示例如下:Entity framework 如何访问具有复合键的表';t模型首先使用代码?,entity-framework,ef-code-first,poco,code-first,entity-framework-5,Entity Framework,Ef Code First,Poco,Code First,Entity Framework 5,我有一个无法更改的现有数据库,但希望使用EF访问。对于90%的数据库,我已经能够让代码优先EF工作,我印象非常深刻 我遇到了一个案例,我想知道如何通过导航属性建模或访问数据 在一种情况下,表是这样的(这个例子完全是虚构的,但代表了问题): 在表“品种”中,组织表示已定义品种的组织。一只狗可以有几个品种,但程序只显示一个,结果由组织id“过滤”——这是程序设置时配置的值 可能存在的数据示例如下: id organizationID Description 1
id organizationID Description
1 1 Basset Hound
2 1 Great Dane
2 2 Grande Dane
组织2选择将该品种称为与组织1不同的品种。唯一主键是id和organizationID的组合。狗有一个品种,但没有定义一个或多个相关组织的属性。它从另一个表或配置值(可能是枚举值)中获取附加信息以查找狗的品种
在我的例子中,要找到一个特定的狗品种,你必须有一个狗id和另一条与程序配置相关的信息(组织id)
狗、品种和组织类如下所示:
public class Dog {
public int id { get; set; };
public string name { get; set; };
public int breedID { get; set; };
public virtual Breed { get; set; }
}
public class Breed {
public int id { get; set; };
public int organizationID { get; set; };
public string description { get; set; };
public virtual Organization { get; set; }
}
public class Organization {
public int id { get; set; };
public string description { get; set; };
}
正如在代码中看到的,我希望在返回一个品种的狗上使用“导航”属性,但我不认为我可以首先在代码中配置它
我尝试了一些不同的方法(在fluent API中,将组织排除在外-因为这很容易),并且还将记录我认为不起作用的方法:
1)
modelBuilder.Entity<Dog>().HasKey(t => t.id);
modelBuilder.Entity<Breed>().HasKey(t => t.id);
modelBuilder.Entity<Dog>().HasRequired(d => d.Breed).WithMany().HasForeignKey(d => d.breedID);
理想情况下,它将像导航集合一样工作,其中EF发挥神奇的作用并返回适当的结果
直观地说,似乎我应该能够使用类似POCO的代码来配置此配置,或者使用/扩展代理来扩展配置,以便在调用访问器时使用我想要的特定查询。或者-看起来我应该能够在任何读操作中填充属性,在写操作中弄脏POCO。我只是对EF不够熟悉,不知道怎么做
这可能吗
作为对第一篇文章的补充,因为我希望保持我的POCO类干净,我想我可能会实现Repository模式来封装像我所描述的那样的复杂查询,并支持其他操作
查看我从代码优先模型生成的EDMX,也不清楚如何从数据库优先的角度实现该模型
任何想法都非常感谢。简而言之,你不能那样做。如果数据库结构不合理(外键引用非唯一列),则必须将其映射到某个位置。在EF配置中不能这样做,因为它是动态的,所以必须在实体类中这样做。如果不直接调用实体类(或助手类)中的上下文,我看不到任何方法可以做到这一点。简而言之,您无法做到这一点。如果数据库结构不合理(外键引用非唯一列),则必须将其映射到某个位置。在EF配置中不能这样做,因为它是动态的,所以必须在实体类中这样做。如果不直接调用实体类(或助手类)中的上下文,我看不出有什么方法可以做到这一点。那太好了。你能给我举个例子说明如何做吗?谢谢我试图配置这个,但没有任何运气。我尝试了一些类似这样的东西:HasRequired(t=>new{t.typeId,otherVariable})。。。问题是,当复合键的另一个组件不是“Dog”表的一部分时,我不知道如何“注入”它。提前谢谢!哦,等等,对不起,我现在知道你的其他情况了,我这样做对你没有帮助。要使用的另一个ID是否存储在数据库的某个位置,或者只有程序知道它?不幸的是,只有程序知道它-这是最初使用数据库的程序工作方式的一部分。谢谢你的回复。问得好,如果你能粘贴一些代表你的问题的代码,那会很有帮助。那太好了。你能给我举个例子说明如何做吗?谢谢我试图配置这个,但没有任何运气。我尝试了一些类似这样的东西:HasRequired(t=>new{t.typeId,otherVariable})。。。问题是,当复合键的另一个组件不是“Dog”表的一部分时,我不知道如何“注入”它。提前谢谢!哦,等等,对不起,我现在知道你的其他情况了,我这样做对你没有帮助。要使用的另一个ID是否存储在数据库的某个位置,或者只有程序知道它?不幸的是,只有程序知道它-这是最初使用数据库的程序工作方式的一部分。感谢您的回复。很好,如果您可以粘贴一些表示您的问题的代码,这将非常有帮助。在这种情况下,在调用Breed的访问器时,是否有方法调用特定的查询?我想知道我是否可以先用类似POCO的EF来补充代码(到目前为止效果很好)。不,你必须自己做,就像你在post中已经包含的代码一样。既然如此,当调用Breed的访问器时,有没有办法调用特定的查询?我想知道我是否可以先用类似POCO的EF补充代码(到目前为止效果很好)。不,你必须自己做,就像你在帖子中已经包含的代码一样。
1)
modelBuilder.Entity<Dog>().HasKey(t => t.id);
modelBuilder.Entity<Breed>().HasKey(t => t.id);
modelBuilder.Entity<Dog>().HasRequired(d => d.Breed).WithMany().HasForeignKey(d => d.breedID);
2)
Change class dog:
Remove:
public virtual Breed { get; set; }
Add:
public virtual ICollection<Breed> Breeds { get; set; }
public Breed Breed {
get {
// Assume 1 is configured organization value
return Breeds.Single(t => t.OrganizationId == 1);
};
set {
Breeds.Add(value);
}
}
Change model:
I don't know how to do this for the given classes. Since it's a Collection, it must look something like
modelBuilder.Entity<Dog>().HasMany(d => d.Breeds)...
but I don't see how to specify that breedID is a foriegn key into the breed table.
3)
Change model to account for composite key (using first set of classes):
modelBuilder.Entity<Breed>().HasKey(b => new { b.id, b.organizationId });
modelBuilder.Entity<Dog>().HasRequired(t => t.Breed).WithMany().HasForeignKey(t => new { t.breedID, configuredValue });
public Breed Breed {
get {
return context.Breed.Where(b => b.id == this.id && b.organizationID == 1).Single();
}
}