提纲
InverseProperty 标注的用途
用于在某一个导航属性上标注其在相关实体上的反向导航属性,构造函数必须指定相关实体上的反向导航属性,且此属性的类型必须和导航属性的反向导航属性一致.
先看不带有 InversePropery 的例子,但是在 EFCore中无法运行
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public User Author { get; set; }
public User Contributor { get; set; }
}
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Post> AuthoredPosts { get; set; }
public List<Post> ContributedToPosts { get; set; }
}
这个例子在 EFCORE中无法创建表.
错误原因,
Unable to determine the relationship represented by navigation property 'User.AuthoredPosts' of type 'List<Post>'.
不能查明到由导航属性 User.AuthoredPosts (类型, List<Post>) 所表示的关系
这个 determine 有 查明/探测/决定的意思. 我们这儿就翻译作 查明 吧.
但是在 EF中,这个可以创建表,只是在 Post表中会有4个外键,
因为 EF找到了 4个关系,
- Post 中的 Author 和 Contributor
- User 中的 AuthoredPosts 和 ContributedToPosts
而EF 不知道这些关系其实是2对导航-反向导航的关系 ,所以采取默认的处理措施,
即给 每一个关系都会在数据库的相关实体中(也就是 Post 表中) 中创建一个外键.
看到这儿就很简单了,
InverseProperty 标注用来标注某一个导航属性在相关实体中的另外一端的反向导航.
所以,它带有一个构造函数,也就是相关实体的导航属性的名称.
稍微改一下代码. 测试InverseProperty指向一个 int 类型的字段,想用这个字段作为外键.
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[InverseProperty(nameof(User.AuthoredPosts)]
public User Author { get; set; }
public User Contributor { get; set; }
public int OtherContributorId { get; set; }
}
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Post> AuthoredPosts { get; set; }
[InverseProperty(nameof(Post.OtherContributorId)]
public List<Post> ContributedToPosts { get; set; }
}
以上代码也无法执行,EFCORE会判断反向导航的属性是否和导航属性的类型是否匹配.
只是报了一个奇怪的错误: System.ArgumentNullException: Value cannot be null. (Parameter 'type')
正确写法如下:
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[InverseProperty(nameof(User.AuthoredPosts)]
public User Author { get; set; }
public User Contributor { get; set; }
}
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Post> AuthoredPosts { get; set; }
[InverseProperty(nameof(Post.Contributor)]
public List<Post> ContributedToPosts { get; set; }
}
至少,比起 EF 来, EFCorer 显得更加智能一点...
网友评论