【问题标题】:EF Core 3: Configure backing field of navigation propertyEF Core 3:配置导航属性的支持字段
【发布时间】:2020-06-22 08:08:21
【问题描述】:

考虑下面的类。它试图保护对 _assignedTrays 的访问。

实际上,它运行良好,因为 EF 自动将支持字段 _assignedTrays 链接到属性 AssignedTrays - 按照惯例 (msdn)

    public class Rack
    {
        private List<Tray> _assignedTrays = new List<Tray>();

        private Rack()
        {
        }

        public Rack(string rackId)
        {
            this.Id = rackId;
        }

        public string Id { get; private set; }

        public IReadOnlyList<Tray> AssignedTrays => this._assignedTrays.AsReadOnly();

        public void Assign(params Tray[] trays)
        {
            this._assignedTrays.AddRange(trays);
        }
    }

问题是,我们的编码风格禁止在变量名中使用下划线 ;-)

根据其他代码示例 (here),应该可以将 _assignedTrays 重命名为 assignedTrays,并明确告知 EF OnModelCreating 中的更改:

    modelBuilder.Entity<Rack>(e =>
    {
        e.Property(t => t.AssignedTrays).HasField("assignedTrays");
    });

但这给了我以下例外:

System.InvalidOperationException: The property 'Rack.AssignedTrays' is of type 'IReadOnlyList<Tray>' which 
is not supported by current database provider. Either change the property CLR type or ignore the property
using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

我在这里缺少什么?它不应该工作吗?

【问题讨论】:

  • 我认为你真的无能为力。解决方法是重命名支持字段,例如 internalAssignedTrays 并添加注释说明为什么不能将其命名为其他名称,以便通过代码审查。
  • 我可以进行不同的映射(Property 方法不适用于导航属性),但没有必要,因为 EF Core 约定 supports your naming style
  • @IvanStoev 但是约定不允许没有下划线的约定。
  • @DavidG 糟糕,文档似乎不完整,&lt;camel-cased property name&gt;(默认的 C# 支持字段命名约定)也受支持 - 可能具有最高优先级。
  • @IvanStoev:你是对的。我想知道为什么不使用 HasField 配置时集成测试会变成绿色,但我将其归咎于“不完整的测试”......

标签: c# entity-framework-core domain-driven-design ef-core-3.1


【解决方案1】:

文档没有反映实际规则,因为&lt;camel-cased property name&gt;(“标准”C# 支持字段命名约定)绝对受支持,甚至可能具有最高优先级。

但是假设您的命名约定不受支持。您仍然可以映射支持字段,但您不能使用 Property fluent API 执行此操作,因为按照 EF Core 术语,导航属性不是“属性”,而是“导航”。这适用于所有 fluent、更改跟踪等 API。

为了配置导航,您需要访问关系构建器。然后您可以使用关联元数据的PrincipalToDependentDependentToPrrncipal 属性来访问/配置关系的两端。

或者直接使用元数据 API(目前还没有专门的 fluent API)。

例如:

modelBuilder.Entity<Rack>()
    .FindNavigation(nameof(Rack.AssignedTrays))
    .SetField("assignedTrays");

【讨论】:

    猜你喜欢
    • 2021-03-31
    • 2021-12-13
    • 1970-01-01
    • 2014-10-09
    • 2018-10-22
    • 2018-10-10
    • 2020-12-02
    • 2020-02-23
    • 1970-01-01
    相关资源
    最近更新 更多