长话短说,我使用 EF Core 8 成功进行了初始迁移。但是,很快我到处发现了一些相当小的问题,并尝试修改它们,但此后尝试进行新的迁移最终会出错并出现非常奇怪的错误。这很令人费解,因为最初的迁移很顺利,但现在却无法正常工作。
我做了一个单独的项目,并尝试一一添加模型类,直到它停止工作。
这是项目仍然有效的设置:
internal class Dictionary
{
public string Name { get; set; }
public bool IsEnabled { get; set; }
public ICollection<DictionaryEntry> Entries { get; set; }
}
internal class DictionaryEntry
{
public string Name { get; set; }
public bool IsEnabled { get; set; }
public Dictionary Dictionary { get; set; }
}
internal abstract class DictionaryEntry<TValue>: DictionaryEntry
{
public TValue Value { get; set; }
}
internal abstract class GroupedEntry<TValue, TEntryGroup>: DictionaryEntry<TValue>
where TEntryGroup : DictionaryEntry
{
public virtual TEntryGroup EntryGroup { get; set; }
}
internal class EntryGroup<TEntry>: DictionaryEntry
where TEntry : DictionaryEntry
{
public virtual ICollection<TEntry> Entries { get; set; }
public virtual EntryGroup<TEntry> Parent { get; set; }
public virtual ICollection<EntryGroup<TEntry>> Children { get; set; }
}
internal class EntryGroup<TGroupEntry, TEntry>: EntryGroup<TEntry>
where TGroupEntry : DictionaryEntry
where TEntry : DictionaryEntry
{
public virtual TGroupEntry GroupEntry { get; set; } = null!;
}
internal class EntryClassA: DictionaryEntry<uint>
{
public virtual EntryClassB LinkedDocumentation { get; set; }
}
internal class EntryClassB: GroupedEntry<uint, EntryGroup_EntryClassAB>;
internal class EntryGroup_EntryClassAB: EntryGroup<EntryClassB, EntryClassA>
添加这些类会导致错误:
internal abstract class Entry_ClassCBase: GroupedEntry<uint, EntryGroup_ClassC>;
internal class Entry_ClassCGroup: Entry_ClassCBase;
internal class Entry_ClassC: Entry_ClassCBase;
internal class EntryGroup_ClassC: EntryGroup<Entry_ClassCGroup, Entry_ClassC>;
在这种特殊情况下,这是由于
无法创建类型为“”的“DbContext”。异常“无法确定“EntryGroup_ClassC.GroupEntry”和“Entry_ClassCGroup.EntryGroup”之间的一对一关系的从属方。要识别关系的从属方,请配置外键属性。如果这些导航不应该属于同一关系,请通过“OnModelCreating”中单独的方法链独立配置它们。有关更多详细信息,请参阅 https://go.microsoft.com/fwlink/?LinkId=724062。尝试创建实例时抛出。有关设计时支持的不同模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728
但是在主应用程序中,当第一次迁移成功创建时,模型已经包含了那些相同的类,所以我不明白错误的突然起源。我可以煞费苦心地把错误一一改正,但我当然不想这么做。我唯一的理论是,当我解决这些问题时,我可能会改组一些使模型工作的代码,但我不明白是哪些。
这是我的背景:
namespace Program
{
sealed class CultureInfoConverter: ValueConverter<CultureInfo, string>
{
public CultureInfoConverter() : base(static (v) => v.Name, static (v) => CultureInfo.GetCultureInfo(v)) { }
}
internal partial class Context(DbContextOptions<Context> options): DbContext(options)
{
public DbSet<Dictionary> Dictionaries { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
_ = modelBuilder.
HasCollation("en_natural", locale: "en-u-kn-true", provider: "icu", deterministic: false);
_ = modelBuilder.UseHiLo(null);
_ = modelBuilder.Owned<Oid>();
_ = modelBuilder.Owned<Version>();
_ = modelBuilder.Entity<Dictionary>().
HasDiscriminator();
_ = modelBuilder.Entity<Dictionary>().Property<uint>("RowVersion").
IsRowVersion();
_ = modelBuilder.Entity<DictionaryEntry>().
HasDiscriminator();
_ = modelBuilder.Entity<DictionaryEntry>().Property<uint>("RowVersion").
IsRowVersion();
_ = modelBuilder.Entity<Dictionary>().Property<ulong>("Id");
_ = modelBuilder.Entity<DictionaryEntry>().Property<ulong>("Id");
}
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
_ = configurationBuilder.Properties<string>().
UseCollation("en_natural").
AreUnicode();
_ = configurationBuilder.Properties<CultureInfo>().
HaveConversion<CultureInfoConverter>();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => _ = optionsBuilder.UseExceptionProcessor();
}
}
所以有几件事需要检查(我能想到的唯一的事情):
EF Core 可能会与复杂继承设置中的关系混淆,特别是一对一关系的哪一侧是依赖的。
EntryGroup_ClassC.GroupEntry
和Entry_ClassCGroup.EntryGroup
似乎就是这种情况。也许尝试在 OnModelCreating
中显式设置外键以澄清映射。
然后继续复杂的继承问题 EF Core 通常需要您为一对一或一对多关系手动定义外键。我想说的是,检查
GroupedEntry
和 EntryGroup
类中的每个关系,并显式设置 HasForeignKey
或使用 WithOne/WithMany
确保每个映射尽可能清晰。