C# 如何基于两列(其中一列可为空)为具有索引唯一数据注释的表设定种子

C# 如何基于两列(其中一列可为空)为具有索引唯一数据注释的表设定种子,c#,.net,sql-server,entity-framework,entity-framework-6.1,C#,.net,Sql Server,Entity Framework,Entity Framework 6.1,我想创建一个表,其中数据唯一性基于多个列(2或3),但其中一个可以为null。 例如: FRUIT WEIGHT UNIT Apple Apple 1 Kg Apple 2 Kg Orange Orange 1 Kg Orange 2 Kg 都将被视为唯一条目。 可以用EF 6.1数据注释来完成吗? 我相信我做到了这一点: [Required] [Index("UniqueIndx", 1)] public string Nam

我想创建一个表,其中数据唯一性基于多个列(2或3),但其中一个可以为null。 例如:

FRUIT   WEIGHT  UNIT
Apple
Apple   1       Kg
Apple   2       Kg
Orange
Orange  1       Kg
Orange  2       Kg
都将被视为唯一条目。 可以用EF 6.1数据注释来完成吗? 我相信我做到了这一点:

[Required]
[Index("UniqueIndx", 1)]
public string Name { get; set; }
[Index("UniqueIndx", 2)]
public float? Weight { get; set; }
[Index("UniqueIndx", 3, IsUnique = true)]
public FormulUnit? Unit { get; set; }
产生:

public override void Up()
{
    AlterColumn("MyDb.Fruits", "Weight", c => c.Single());
    AlterColumn("MyDb.Fruits", "Unit", c => c.Int());
    CreateIndex("MyDb.Fruits", new[] { "Name", "Weight", "Unit" }, 
                 unique: true, name: "UniqueIndx");
}
从我对迁移创建的Up方法的理解来看,唯一性是基于所有3列的,而不仅仅是我写注释的最后一列。这对我来说没关系,这就是我想要的

我仍然有在那张桌子上播种的问题。我在AddOrUpdate方法上遇到了如下错误:

System.InvalidOperationException: The binary operator Equal is not defined for the types 'System.Nullable`1[System.Single]' and 'System.Single'.
用于:

我错过什么了吗? 谢谢,我刚刚调试了,抛出错误的代码就在里面

下面是导致错误的部分代码摘录

var matchExpression
    = identifyingProperties.Select(
        pi => Expression.Equal(
            Expression.Property(parameter, pi.Single()),
            Expression.Constant(pi.Last().GetValue(entity, null))))
或者,您可以通过这样做来复制错误

var fr1 = new Fruit { Weight = 1 };
var epe = Expression.Property(Expression.Constant(fr1), "Weight");
var ec = Expression.Constant(fr1.Weight);
var ee = Expression.Equal(epe, ec);
我不确定为什么
Float?
不能被接受,也许其他人可以解释


但是,如果您可以只使用或手动检查是否添加或更新,而不是使用
AddOrUpdate
,那么这将起作用。

更新2:

下面是我认为我的错误并给出了可能的解决方案。但我又错了。尽管下面的代码使用基于3个条件的索引将新记录添加到数据库中,因为它会在过程中创建匿名类型的新对象,但会丢失外键关系。 若您有一个父类,我们称之为包含许多水果的杂货店,那个么seed方法将不会用下面给定的代码更新这些关系

重新开始工作


我的逻辑是错误的

如果我们有一个基于多个标准的唯一索引,我们如何知道要更新哪个记录?3个条件中有一个不同的记录很可能是一个新记录,也可能是一个需要更新的旧记录,但这不是编译器可以判断的

每个记录都需要手动添加

谢谢你,尤利安

更新: 对于那些陷入同样困境的人,下面是我如何解决这个问题的(在其他Stackoverflow帖子的帮助下)

首先,您必须知道水果实体有一个ID为的基本实体,所以在这里看不到它。 为了更好地理解,需要采取以下步骤:

  • 将您的数据库集从上下文放入一个匿名类型列表中 来自不需要比较的属性
  • 将匿名类型列表放入强类型列表(您的 实体类型,在本例中为:水果)
  • 创建一个新列表,在其中仅从数据库中不存在的种子对象中进行选择
  • 将所有这些新对象添加到上下文(然后是context.save())

    var SeedFruits=新列表{fr1,fr2,fr3}

    var result=来自context.Fruits中的 选择新的{a.名称、a.重量、a.单位}

    List DBFruitsList=result.AsEnumerable() .选择(o=>新水果 { 名称=o.名称, 重量=o.重量, 单位=o.单位 }).ToList()

    唯一水果列表= 种子果实中的人工智能 哪里DBFruitsList.Any(x=>x.Name==ai.Name&&x.Weight==ai.Weight&&x.Unit==ai.Unit) 选择人工智能

    foreach(在唯一水果列表中更新水果) { context.Fruits.Add(水果更新); }


  • 什么是公式?FormulUnit是一个枚举。
    Fruit
    的主键是什么?Fruit的主键位于Fruit和其他实体从中继承的基类中。我认为尝试AddOrUpdate是错误的,但后来由于不使用AddOrUpdate,我遇到了另一个问题。我现在很烦恼。我将取消实体中的所有索引注释。
    var fr1 = new Fruit { Weight = 1 };
    var epe = Expression.Property(Expression.Constant(fr1), "Weight");
    var ec = Expression.Constant(fr1.Weight);
    var ee = Expression.Equal(epe, ec);