gpt4 book ai didi

c# - Entity Framework Core 不支持具有多对多关系的通用抽象实体

转载 作者:太空宇宙 更新时间:2023-11-03 12:33:38 26 4
gpt4 key购买 nike

我在 EF Core 1.1 中遇到了一个奇怪的问题。我正在尝试构建可以标记某些实体的应用程序,因此我为关系表列表创建了一个抽象通用类。问题是,EF 似乎不支持具有 FK(Id 属性有效)的通用抽象类。

这里是模型:

public abstract class TaggedEntityBase<T> : EntityBase
{
public ICollection<T> EntityTags { get; set; }
public List<Tag> Tags { get { return EntityTags?.Select(x => x.Tag).ToList(); } }
}

public class AddressTag
{
public long TagId { get; set; }
public Tag Tag { get; set; }
public long EntityId { get; set; }
public Address Entity { get; set; }
}

public class Address : TaggedEntityBase<AddressTag>
{
public string Street { get; set; }
public string City { get; set; }
}
public class Tag : EntityBase
{
public string Name { get; set; }
public virtual ICollection<AddressTag> AddressTags { get; set; }
}

模型构建器映射:

public DbSet<Address> Addresses { get; set; }
public DbSet<AddressTag> AddressTag { get; set; }
public DbSet<Tag> Tags { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AddressTag>()
.ToTable("AddressTag");

modelBuilder.Entity<AddressTag>()
.HasKey(t => new { t.EntityId, t.TagId });
modelBuilder.Entity<AddressTag>()
.HasOne(pt => pt.Entity)
.WithMany(p => p.EntityTags)
.HasForeignKey(p => p.EntityId);
modelBuilder.Entity<AddressTag>()
.HasOne(pt => pt.Tag)
.WithMany(p => p.AddressTags)
.HasForeignKey(p => p.TagId);

}

EF 尝试获取标签时出现错误

An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in Microsoft.EntityFrameworkCore.dll Additional information: Invalid column name 'AddressId'.

我什至没有那个 Id 约定。

注意:当我明确放置 public ICollection<AddressTag> EntityTags { get; set; } 时在 Address POCO 中,然后它可以完美运行,包括 EntityTags.Tag。感谢您的帮助:)

最佳答案

该问题与通用和/或抽象基实体类无关。

首先,为了编译您的示例模型,我添加了以下类

public abstract class EntityBase
{
public long Id { get; set; }
}

public abstract class EntityTagBase
{
public long TagId { get; set; }
public Tag Tag { get; set; }
}

修改了AddressTag类如下:

public class AddressTag : EntityTagBase
{
public long EntityId { get; set; }
public Address Entity { get; set; }
}

并添加了where T : EntityTagBase约束到 TaggedEntityBase<T>类允许 Tag内部属性访问器 Select(x => x.Tag) .

到目前为止一切顺利。 Tag生成的迁移的相关部分如下所示:

migrationBuilder.CreateTable(
name: "Tags",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
AddressId = table.Column<long>(nullable: true),
Name = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Tags", x => x.Id);
table.ForeignKey(
name: "FK_Tags_Addresses_AddressId",
column: x => x.AddressId,
principalTable: "Addresses",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});

参见 AddressId列和 FK 到 Addresses table ?这是为什么?因为你的Tags属性:

public List<Tag> Tags { get { return ...; } }

这可能是映射只读集合属性的当前 EF Core 错误,但实际效果是它考虑了 Address 之间的一对多关系。和 Tag这当然不是您的意图。

一般来说,我会建议保持实体模型干净,不要包含此类“辅助”属性 - 集合和引用类型。它们看起来像导航属性,但实际上不是,并且很容易在查询中错误地使用它们,这将完全改变执行计划并导致意外异常或错误结果(如果未加载底层属性)。不是说违反一般规则不创建属性返回List它不是类的成员,而是在每个属性访问调用中创建的。

很快,只需删除该属性,问题就会消失。或者如果你坚持保留它,那就用NotMapped装饰它数据注释:

[NotMapped]
public List<Tag> Tags { get { return ...; } }

关于c# - Entity Framework Core 不支持具有多对多关系的通用抽象实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41825478/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com