外键长的多对一迁移失败
Posted
技术标签:
【中文标题】外键长的多对一迁移失败【英文标题】:Many to one migrations fails on foreign key long 【发布时间】:2017-04-12 03:53:41 【问题描述】:我有 2 个模型:
public class Text
public long Id get; set;
public string Text get; set;
public class User
public int Id get; set;
public ICollection<Text> Texts get; set;
我的用户模型是这样的
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.Id).IsRequired();
当我尝试运行时:
dotnet ef 迁移添加
我收到此错误:
具有外键属性 'Id' : long 无法定位主 key 'Id' : int 因为它不兼容。配置主体 键或一组兼容的外键属性 关系。
更新:
新模型应该能够拥有表格文本的集合,例如:
public class Customer
public int Id get; set;
public ICollection<Text> Texts get; set;
....
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.Id).IsRequired();
【问题讨论】:
一个是int
,另一个是long
是的,但我怎么能说关键属性类型是长的
有类似的情况。为了将来参考,[此链接] (entityframeworkcore.com/knowledge-base/48998620/…) 有所帮助。从流行的答案...[Column(TypeName = "int")] public long Id get; set;
应该可以工作。
【参考方案1】:
使用 EF Core 时遇到类似问题,但不想在依赖实体 Text 中包含(在我的类中等效)UserId,只是为了让 EF 满意。终于发现可以替换关系中使用的主键(UserId) 使用 HasPrincipalKey()
modelBuilder.Entity<User>()
.HasMany(t => t.Texts)
.WithOne()
.HasPrincipalKey(u => u.Text);
【讨论】:
【参考方案2】:在 EF 上下文配置中,特别是在 HasForeignKey()
中,您应该指定 Text
模型上的哪个属性应该是指向 User
模型的外键?
既然User
模型的主键是int
,那么从Text
指向User
的外键自然也应该是int
。
我认为您犯的错误是您将Text
的PK 配置为关系Text
-> User
的FK。尝试将您的 Text
模型更改为:
public class Text
public long Id get; set;
public string Text get; set;
public int UserId get; set;
你的配置:
e.HasMany(o => o.Texts).WithOne().HasForeignKey(d => d.UserId).IsRequired();
【讨论】:
如果我添加一个新模型:具有相同的客户,ICollectionint
,那么您可以用来标识该行的唯一数据类型是int
,否则将无法识别它。
我仍然不确定您要达到的目标。 Customer
模型与 User
模型相同。除此之外,您还没有解决外键问题。如果 1 个 User
可以有超过 1 个 Text
,即使您有相同类型的 ID,如果没有 Text
上的附加 (UserId
) 属性,也无法实现这种关系。
哦,现在我明白了,非常感谢您的解释!【参考方案3】:
首先,请更改您的模型命名,
public class Text
public long Id get; set;
public int UserId get; set; // add a foreign key that could point to User.Id
public string Body get; set; //you cannot have a string property called "Text".
public virtual User Owner get; set;
public class User
public int Id get; set;
public virtual ICollection<Text> Texts get; set; = new HashSet<Text>();
builder.Entity<Text>(table =>
table.HasKey(x => x.Id);
table.HasOne(x => x.User)
.WithMany(x => x.Texts)
.HasForeignKey(x => x.UserId)
.HasPrincipalKey(x => x.Id)//<<== here is core code to let foreign key userId point to User.Id.
.OnDelete(DeleteBehavior.Cascade);
);
我们必须弄清楚引用哪个键的原因是因为有多个主键。我在 MSDN 看到过一次,但是找不到了。
你可以为外键使用影子属性,现在看起来很流行。
public class Text
public long Id get; set;
public string Body get; set;
public virtual User Owner get; set;
public class User
public int Id get; set;
public virtual ICollection<Text> Texts get; set; = new HashSet<Text>();
builder.Entity<Text>(table =>
table.HasKey(x => x.Id);
// Add the shadow property to the model
table.Property<int>("UserId");
table.HasOne(x => x.User)
.WithMany(x => x.Texts)
.HasForeignKey("UserId")//<<== Use shadow property
.HasPrincipalKey(x => x.Id)//<<==point to User.Id.
.OnDelete(DeleteBehavior.Cascade);
);
【讨论】:
【参考方案4】:您可以简单地删除所有迁移或产生该 Id 的迁移,删除数据库(如果它很小或没有数据)并添加一个干净的迁移
【讨论】:
【参考方案5】:我在一对一的关系中也面临同样的问题。如果您在一对一的关系中遇到问题。然后试试这个:
public partial class document
public document()
groups = new group();
public int? group_id get; set;
public virtual group groups get; set;
[Table("group")]
public class group
[Key]
[Column("group_id")]
public int group_id get; set;
[ForeignKey(nameof(group_id))]
public virtual document document get; set;
每个文档都有一个组。所以,我们可以考虑这些设置。
modelBuilder.Entity<group>().HasOne(a => a.document)
.WithOne(y => y.groups).HasForeignKey<document>(b => b.group_id);
【讨论】:
以上是关于外键长的多对一迁移失败的主要内容,如果未能解决你的问题,请参考以下文章