如何在 EF Core 2.2 中使用支持字段设置只读集合属性

Mar*_*cin 9 c# dbcontext entity-framework-core

我正在尝试创建一个实体类,它将通过只读属性公开相关集合,如下所示:

public class MyEntity: Entity
{
    public int Id{ get; private set; }
    private IList<RelatedEntity> _relatedEntities = new List<RelatedEntity>();
    public IReadOnlyList<RelatedEntity> RelatedEntities => _relatedEntities.ToList().AsReadOnly();
}
Run Code Online (Sandbox Code Playgroud)

构建器类如下所示:

public void Configure(EntityTypeBuilder<MyEntity> builder)
{
    builder.HasKey(x=>x.Id);
    builder.Property<IReadOnlyList<RelatedEntity>>("RelatedEntities")
        .HasField("_relatedEntities ")
        .UsePropertyAccessMode(PropertyAccessMode.Field);
}
Run Code Online (Sandbox Code Playgroud)

它可以构建,但在运行时崩溃,但有以下例外:

InvalidOperationException:“IList”类型的指定字段“_latedEntities”不能用于“IReadOnlyList”类型的属性“MyEntity.RelatedEntities”。只能使用可从属性类型分配的类型的支持字段。

您能提供一个如何处理这个问题的工作示例吗?

Moh*_*and 8

我检查了这个并且它起作用了:

private readonly List<RelatedEntity> _relatedEntitys;
public IReadOnlyCollection<RelatedEntity> RelatedEntitys => _relatedEntitys;
Run Code Online (Sandbox Code Playgroud)

并且配置必须如下所示:

    builder.HasMany(x => x.RelatedEntitys)
        .WithOne()
        .IsRequired()
        .HasForeignKey(x => x.RelatedEntityId)
        .OnDelete(DeleteBehavior.Cascade);

    builder.Metadata
        .FindNavigation("RelatedEntitys")
        .SetPropertyAccessMode(PropertyAccessMode.Field);
Run Code Online (Sandbox Code Playgroud)


小智 5

EF core 要求您使用具体类型作为支持字段。您需要将代码更改为:

private readonly List<RelatedEntity> _relatedEntities = new List<RelatedEntity>();
public IReadOnlyList<RelatedEntity> RelatedEntities => _relatedEntities.ToList();
Run Code Online (Sandbox Code Playgroud)


Den*_* W. 1

错误消息响亮而清晰:

IList 不可分配给 IReadOnlyList

将属性类型更改为与支持字段相同的类型即可解决问题。

更新:

因为IEnumerable<T>默认情况下是只读的,所以我相信这将是您最好的选择。

    public class MyEntity: Entity
    {
        public int Id { get; private set; }

        private readonly List<RelatedEntity> _relatedEntities = _collection.ToList().AsReadOnly();

        public IEnumerable<RelatedEntity> RelatedEntities => _relatedEntities;
    }
Run Code Online (Sandbox Code Playgroud)

按如下方式更新您的 Fluent API:

    builder.HasKey(x=>x.Id);
    builder.Metadata.FindNavigation("RelatedEntities")
        .UsePropertyAccessMode(PropertyAccessMode.Field);
Run Code Online (Sandbox Code Playgroud)