【问题标题】:Check the existence of a record before inserting a new record在插入新记录之前检查记录是否存在
【发布时间】:2012-03-06 10:40:23
【问题描述】:

我是第一次使用 Ado.net 实体框架,我需要在将其插入数据库之前检查此记录是否存在。最好我会搜索 AuthodSSID 是否存在而不是密钥(AuthorID)。我正在使用 VS2010,Framework 4。System.Data.Entity 是 3.5.0.0。

我用谷歌搜索,但没有找到这个问题的答案。

PublishingCompanyEntities publishContext;
publishContext = new PublishingCompanyEntities();

private void createNew_Click(object sender, EventArgs e)
{
    Author newAuthor = new Author();
    newAuthor.FirstName = firstName.Text;
    newAuthor.LastName = lastName.Text;
    newAuthor.AuthodSSID = 20;
    newAuthor.AuthorID = 10
//Check if record exist here
    publishContext.AddToAuthor(newAuthor);//insert if does not exist

}

【问题讨论】:

标签: c# entity-framework


【解决方案1】:

EF v5.0+ 中有所谓的“upsert”操作

publishContext.Author.AddOrUpdate(x => x.Id, newAuthor)

AddOrUpdate 可以在“System.Data.Entity.Migrations”命名空间中找到,所以不要忘记添加:

using System.Data.Entity.Migrations;

AddOrUpdate 操作不是原子操作。但是 *if (existingAuthorCount == 0) {// Do your insert} 也不是。

【讨论】:

  • 怎么了:DDDDDD
【解决方案2】:

这样的事情应该可以工作:

if (publishContext.Author.Select(a => a.AuthodSSID).Where(id => id == 20).Take(1) == null)
    // It doesn't exist
else
    // It does exist

根据我(尽管是基本的)理解,这应该会产生一个相当于以下内容的 SQL 语句:

SELECT TOP(1) AutodSSID FROM Author WHERE AuthodSSID = 20;

另一种更简单的方法可能是使用Any 扩展方法:

if (!publishContext.Author.Any(a => a.AuthodSSID == 20))
    // Put your insert logic here.

【讨论】:

  • 如果您想更新作者(如果确实存在),这将起作用并且是最好的。但是,这将为作者选择所有列,您可能不需要。按照我的回答进行计数会更有效率。
  • @Jacob - 计数实际上与包含单个列的选择相同,但使用SingleOrDefault 我认为它会在TOP 1 处执行COUNT(*) 仍然需要所有记录,还是我遗漏了什么?
  • 好问题。我对TOP 1 的担忧是,所有 columns 仍会为该行返回。 COUNT 可能需要对数据库进行更多的表扫描,但只会返回一个整数。也许最好的选择是做一个Where,然后是主键的Select,然后是Take(1)。这应该可以解决这两个问题。
  • @Jacob - 有点像我目前的答案?
  • 没有。您当前的答案返回所有列。
【解决方案3】:

从 .NET 的角度来看,我个人更喜欢这种方法。它更干净,如果您关心速度(在 .NET 中),它会更高效,但是 SQL 不是那么快;

private bool CheckIfEntityRecordExists(Entity e)
{
    var retVal = false;
    using (var db = new EntityContext())
    {
        retVal = db.AdviserClients.Any(a => a.Id == e.Id);
    }
    return retVal;
}

因此,对于高效的 SQL 语句,以下是最好的:

private bool CheckIfEntityRecordExists(Entity e)
{
    var retVal = false;
    using (var db = new EntityContext())
    {
        retVal = db.AdviserClients.Count(a => a.Id == e.Id) > 0;
    }
    return retVal;
}

【讨论】:

  • 虽然我赞成你的回答,但从性能角度来看,应该使用 db.context.Any() 因为 db.contex.count() 将迭代所有数据,而 .Any 只会在第一次匹配时停止.
【解决方案4】:

您需要做的就是(使用 linq)搜索具有该 ID 的作者。

Where() 方法将返回您只需要一个作者的集合,因此您使用 FirstOrDefault() 它返回第一个元素,如果没有则返回 null。您还可以使用SinglOrDefault,如果列表中有多个元素,则会引发异常,或者只返回该元素。

似乎@Jacob 有一个出色、更有效的方法!

var author = publishContext.Authors.Where
                               (a=>a.AuthodSSID == 10).FirstOrDefault();
if(author == null) //none exist
{//don't bother creating one unless you need to..
    Author newAuthor = new Author();
    newAuthor.FirstName = firstName.Text;
    newAuthor.LastName = lastName.Text;
    newAuthor.AuthodSSID = 20;
    newAuthor.AuthorID = 10
    publishContext.AddToAuthor(newAuthor);//insert if does not exist
}

【讨论】:

    【解决方案5】:

    检查记录是否存在的唯一方法是查询记录并查看是否有任何返回:

    var existingAuthorCount = publishContext.Author.Count(a => a.AuthodSSID == 20);
    if (existingAuthorCount == 0) 
    {
        // Do your insert
    }
    

    【讨论】:

    • 工作,只需要弄清楚为什么 .Count 没有出现。简单,使用 System.Linq;在顶部失踪了!咳咳!!
    • 来自臭名昭著的 Eric Lippert 的明智建议:你的罐子里装满了硬币。有人问你“那个罐子里有硬币吗?”。 你数一数,然后将答案与零进行比较,还是看看罐子里是否至少有一便士? (Citation)。此解决方案的性能将取决于 Author 中包含的行数。我已经更新了我的答案,将结果查询限制为仅查找 1。
    • 不能使用 publishContext.Author.Any(a => a.AuthodSSID == 20) 还是 .Any() 在 EF 中不可用?
    • 我会重申特雷弗所说的话。我目前正在使用 .Any 在我认为相同的情况下。
    • 是的,如果您的 EF 版本支持 Any,请使用 @M.Babcock 的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多