检查记录是否存在后,SaveChanges会给出DbUpdateException

时间:2017-04-05 13:27:29

标签: c# sql-server entity-framework-6

我有一个表在两列上有唯一索引, F1 Kant [1]。只有主键(这是一个整数Id)和这个索引没有外键。

在添加新记录之前,我会检查数据库中是否存在具有此索引的记录。[2] 我知道它没有! ExistsLaserData 返回false。

然后我将记录添加到 DbSet 并执行 SaveChanges 但现在我得到了一个异常

  

DbUpdateException:SqlException:违反UNIQUE KEY约束   'IX_laserdata_F1_Kant'。无法在对象中插入重复键   'dbo.LaserData'。重复键值为(123456,NULL)。

这是我添加的记录!

使用

初始化上下文
LaserDataContext context = new LaserDataContext();
OrderBy(x => x.F1).ThenBy(x => x.Kant).ToList();

我正在使用的两种方法

public bool ExistsLaserData(string article, string kant)
{
    bool result = false;
    var found = _context.LaserData.Where(x => x.F1 == article && x.Kant == kant).FirstOrDefault();
    if (found != null)
    {
        result = true;
    }

    return result;
}

public void AddLaserData(ref LaserData d)
{
    try
    {
        _context.LaserData.Add(d);
        _context.SaveChanges();
    }
    catch (Exception ex)
    {
        throw;
    }

}

当我检查记录时为什么记录不存在?或者当我执行SaveChanges时为什么记录存在?

[1]这个数据库的开头是一个Excel文档,因此名字很奇怪......

[2]我不想跳过ExistLaserData检查,所以请不要建议我只使用例外。

4 个答案:

答案 0 :(得分:0)

我认为您应该将文章转换为整数,然后检查是否存在。

正如你所说F1是int而article是字符串所以你无法比较它们。

然后您可以使用它来添加或更新:

LaserData found = _context.LaserData.FirstOrDefault( p => p.F1==(int) article);
if(found == null)
{
    _context.LaserData.Add(d);
    _context.SaveChanges();
}

我希望这会对你有所帮助。也许你需要解释更多,如果这不是你想要的。

如果文章类型与F1类似,那么你可以在没有强制转换的情况下写入int:

LaserData found = _context.LaserData.FirstOrDefault( p => p.F1== article);

如果它不是唯一的,你不必检查kant。但你可以检查一下你是否喜欢。

编辑: 用这个:

public bool ExistsLaserData(string article, string kant)
{
bool result = false;
LaserData found = _context.LaserData.FirstOrDefault(x => x.F1 == article && x.Kant == kant);
if (found != null)
{
    result = true;
}

return result;

}

答案 1 :(得分:0)

在这里,您要检查同一行中的两个值,并且仅当两个键对于单个行都相同时才返回一行。

你能试试吗?而不是&& ,使用||

public bool ExistsLaserData(string article, string kant)
{
    bool result = false;
    var found = _context.LaserData.Where(x => x.F1 == article || x.Kant == kant).FirstOrDefault();
    if (found != null)
    {
        result = true;
    }

    return result;
}

答案 2 :(得分:0)

很可能您的kant属性未正确映射。这将解释异常和代码的行为。

  • Exception声明您尝试为null插入kant值,这是有意义的,因为EF由于映射不正确而从未发送过值。
  • 只要您未将ExistsLaserData传递给false参数的方法,
  • null始终会返回kant。这会导致您的代码始终尝试使用AddLaserData方法。

因此,修复方法是确保正确映射此属性并更正列。

如果不是,那么您尝试插入多个具有相同F1值但具有null kant值的记录,这将破坏唯一索引。唯一的方法是使用where过滤器更改索引,以便仅检查kant何时有值。

CREATE UNIQUE NONCLUSTERED INDEX [IX_laserdata_F1_Kant] ON dbo.LaserData (F1 ASC, Kant ASC) WHERE (Kant IS NOT NULL)

答案 3 :(得分:0)

好的,我找到了错误发生的地方,它与ExistsLaserData无关。 ExistsLaserData工作正常!

因为这是一个全新的问题,所以我会提出一个新问题

感谢您提出的所有建议,我将使用其中一些建议!

PS!作为预告片。在SaveChanges事件的重写中,我Trim()所有字符串都是字符串。这会使base.SaveChanges抛出异常......