【问题标题】:Set a value comparer in ASP.NET Core 3.1在 ASP.NET Core 3.1 中设置值比较器
【发布时间】:2020-01-24 04:38:35
【问题描述】:

我在我的 DBContext 中使用了“HasConversion”来定义一个 JSonArray(语言/值)并将其保存为一个文本字段,它的作用就像一个魅力,我在我的解决方案中添加了一个新项目,但没有任何改变我在添加有关“设置值比较器”的迁移时遇到新错误。

我的模型是这样的:

    public class Brand
    {
        public int Id { get; set; }
        public new IList<LangValue> Name { get; set; } = new List<LangValue>();
    }

DBContext 是这样的:

    modelBuilder.Entity<Brand>(t =>
    {

        t.Property(p => p.Name).HasConversion(
            v => JsonConvert.SerializeObject(v, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include}),
            v => JsonConvert.DeserializeObject<IList<LangValue>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include})
         );
    });

它工作得很好,但是在添加一个新项目后,我在添加迁移时出现黄色错误,并且模型没有添加到新数据库中。

Microsoft.EntityFrameworkCore.Model.Validation[10620] 实体类型“品牌”上的属性“名称”是具有值转换器但没有值比较器的集合或枚举类型。设置一个值比较器以确保正确比较集合/枚举元素。

【问题讨论】:

    标签: asp.net-core dbcontext data-conversion jsonconverter entity-framework-core-3.1


    【解决方案1】:

    来自ValueComparer docs https://docs.microsoft.com/en-us/ef/core/modeling/value-comparers#mutable-classes的解释

    列表属性的典型值转换可能会将列表与 JSON 相互转换:

    modelBuilder
        .Entity<EntityType>()
        .Property(e => e.MyProperty)
        .HasConversion(
            v => JsonSerializer.Serialize(v, null),
            v => JsonSerializer.Deserialize<List<int>>(v, null));
    

    这需要在属性上设置 ValueComparer&lt;T&gt; 以强制 EF Core 使用与此转换的正确比较:

    var valueComparer = new ValueComparer<List<int>>(
        (c1, c2) => c1.SequenceEqual(c2),
        c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
        c => c.ToList());
    
    modelBuilder
        .Entity<EntityType>()
        .Property(e => e.MyProperty)
        .Metadata
        .SetValueComparer(valueComparer);
    

    【讨论】:

    • 你是说不用HasConversion?我看到您输入了SetValueComparer 并传递了一个定义的valueComparer,但我看不到与接收converterHasConvertion 没有任何联系(OP 已匿名传递)。我通常有new ValueConverter&lt;T,U&gt;(a =&gt; a.ToU(),b =&gt; b.ToT())
    【解决方案2】:

    来自ValueComparer class documentation

    为 CLR 类型指定自定义值快照和比较 不能与 Equals(Object, Object) 进行比较和/或需要 拍摄快照时的深层/结构副本。例如,数组 如果要检测突变,原始类型将需要两者。

    快照是将值的副本创建到 快照,以便以后可以对其进行比较以确定它是否已更改。 对于某些类型,例如集合,这需要是 集合,而不仅仅是引用的浅表副本。

    您可以在此问题上找到有关如何设置 ValueComparer 的更多信息:

    https://github.com/dotnet/efcore/issues/17471

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      • 2020-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 1970-01-01
      相关资源
      最近更新 更多