EF代码优先:重复的外键(一个来自名称约定,一个来自导航属性) [英] EF Code First: Duplicate foreign keys (one from name convention, one from navigation property)
问题描述
我正尝试使用EF Code First创建一个SQL数据库。
I'm trying to create an SQL database by using EF Code First.
假设我有以下代码:
public class Account
{
public int Id;
public ICollection<User> Users;
}
public class User
{
public int Id;
public int AccountId;
}
public class AccountContext : DbContext
{
public DbSet<Account> Accounts;
public DbSet<User> Users;
}
(请注意,缺少任何Fluent API命令或数据注释;我想
(Note the lack of any Fluent API commands or Data Annotations; I want to do this by convention.)
创建数据库后,我在Users表中获得以下字段:
When the database is created, I get the following fields in the Users table:
Id
AccountId
Account_Id
为什么EF不能理解 AccountId是指Account的 Id主键这一事实?我希望避免在可能的情况下使用Fluent API / DA手动进行映射,并且希望避免在用户上拥有帐户导航属性。
Why isn't EF picking up on the fact that "AccountId" refers to the "Id" primary key (by convention) of Account? I want to avoid mapping this manually with Fluent API/DA if possible, and I want to avoid having the Account navigation property on User.
推荐答案
通过数据注释(非常快速)或流利的映射,我只有两种方法可以知道如何执行您要执行的操作。您不能只说 public int AccountId;
并期望一切正常。
There are only two ways i know how to perform what you are looking to do, either by Data Annotation (Very quick) or Fluent Mapping. You can't just say public int AccountId;
and expect everything to work.
Fluent API映射双向
public class Account
{
public int Id { get; set; }
public ICollection<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public Account Account { get; set; }
}
public class AccountContext : DbContext
{
public AccountContext()
: base("DefaultConnection")
{
}
public DbSet<Account> Accounts { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasRequired(u => u.Account)
.WithMany(a => a.Users)
.HasForeignKey(u => u.AccountId);
}
}
双向数据注释
public class Account
{
[Key]
public int Id { get; set; }
public ICollection<User> Users { get; set; }
}
public class User
{
[Key]
public int Id { get; set; }
[ForeignKey("Account"), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int AccountId { get; set; }
public Account Account { get; set; }
}
// and of course you need your context class, but with less code
public class AccountContext : DbContext
{
public AccountContext()
: base("DefaultConnection")
{
}
public DbSet<Account> Accounts { get; set; }
public DbSet<User> Users { get; set; }
}
没有双向数据注释或Fluent API映射
public class Account
{
public int Id { get; set; } //as Id in Accounts Table
public ICollection<User> Users { get; set; }
}
public class User
{
public int Id { get; set; } //as Id in Users Table
public Account Account { get; set; } // as Account_Id in Users Table
}
// and of course you need your context class, but with less code
public class AccountContext : DbContext
{
public AccountContext()
: base("DefaultConnection")
{
}
public DbSet<Account> Accounts { get; set; }
public DbSet<User> Users { get; set; }
}
我希望这可以帮助您或其他有疑问的人
I hope this helps you or anyone else in doubt
编辑
如果要避免使用双向
导航,然后像这样更改个用户
If you want to avoid Bi-Directional
navigation then make changes to Users
like this
public class User
{
public int Id { get; set; }
//delete below from User class to avoid Bi-directional navigation
//public Account Account { get; set; }
}
注意:未经测试,但逻辑是声音
Note: Not tested but the logic is sound
这篇关于EF代码优先:重复的外键(一个来自名称约定,一个来自导航属性)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!