我正在使用Entity Framework Code First并遇到了一个小问题。
我有两张桌子:
User
+--------+-----------+
| id | name |
+--------+-----------+
| def789 | Bob Smith |
+--------+-----------+
Actions
+--------+--------------+-------------+
| id | grantedTo_id | details |
+--------+--------------+-------------+
| abc123 | def789 | some detail |
+--------+--------------+-------------+
假设3 Id字段是用于此目的的GUID。
我的课程类似于:
User
{
public Guid id {get; set;}
public string name {get; set;}
}
Actions
{
public Guid id {get; set;}
public User grantedTo {get; set;}
public string details {get; set;}
}
我的问题是,由于类将grantedTo
定义为User类型,因此它不会从数据库中返回任何内容(因为它是Guid类型)。
例如,如果我做一些简单的事情:
var action = db.Action.ToList()
foreach (var a in db.Action)
{
var user = a.GrantedTo
}
然后用户包含null。
如何获取Id引用的用户?
这些是先完成的代码,我没有修改它们。是否有描述符或我应该使用的东西?我以为我可以这样做:
var action = db.Action.ToList()
foreach (var a in action)
{
var user = db.Users.Find(...???)
}
但是,由于GUID也没有回来,所以我不知道该放什么。
答案 0 :(得分:3)
正如Entity Framework Loading Related Entities文档主题中所述,EF支持三种加载相关数据的方法 - 急切加载,延迟加载和显式加载。
由于grantedTo
属性未标记为virtual
,因此不适用于延迟加载,这是EF自动加载相关数据的三种方式。而在另外两个EF中,仅通过您的显式请求执行此操作,而另一方则为您提供更好的控制。
例如,使用Include
方法(急切加载)
var action = db.Action.Include(a => a.grantedTo).ToList();
将填充列表中操作的grantedTo
属性。
这样做的另一个好处是它与EF Core兼容,它(目前)不支持延迟加载。
答案 1 :(得分:1)
如果您使用Code First,则需要将Action定义更改为:
public class Action
{
[Key]
public Guid ActionId { get; set; }
// ...
public Guid GrantedToId { get; set; }
[ForeignKey("GrantedToId")]
public virtual User GrantedTo { get; set; }
// ...
}
如果您使用的是EF6,则可以使用EntityTypeConfiguration设置关系,而无需定义FK属性:
public class ActionConfiguration : EntityTypeConfiguration<Action>
{
public ActionConfiguration()
{
ToTable("Actions");
HasKey(x => x.ActionId);
HasRequired(x => x.GrantedTo)
.WithMany()
.Map(x => x.MapKey("GrantedToId"))
.WillCascadeOnDelete(false);
}
}
我对EF的偏好是使用实体类型配置,因为我更喜欢模式优先开发,它让我可以更好地控制如何设置映射。我不喜欢同时具有导航属性和FK属性,因为您在两者上都有公共设置器。这会留下各种丑陋的场景,你可能有FK,但没有加载引用......或者当更改引用时,如果FK字段不匹配会发生什么,或者你设置FK而不更新引用。