EntityFramework,如果不存在则插入,否则更新

Pou*_*sen 23 sql entity-framework insert sql-update

我有一个实体集国家,反映了数据库表'<'char(2),char(3),nvarchar(我的数据库中的50>).

我有一个解析器返回一个解析国家的Country []数组,并且正在以正确的方式更新它.我想要的是:采取一系列国家,对于那些尚未在数据库中插入它们的国家,以及那些现有的更新,如果任何字段不同.如何才能做到这一点?

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
       //Code missing


    }
}
Run Code Online (Sandbox Code Playgroud)

我在想类似的东西

for(var c in data.Except(db.Countries)) but it wount work as it compares on wronge fields.
Run Code Online (Sandbox Code Playgroud)

希望以前有人遇到过这个问题,并为我提供解决方案.如果我不能使用Country对象并插入/更新它们的数组很容易,我不会看到使用框架的好处,因为从表演者我认为更快写一个自定义的sql脚本插入它们而不是ect检查一个国家插入前已经在数据库中?

请改为查看帖子的答案.

我将override equals添加到我的国家/地区类:

    public partial class Country
{

    public override bool Equals(object obj)
    {
        if (obj is Country)
        {
            var country = obj as Country;
            return this.CountryTreeLetter.Equals(country.CountryTreeLetter);
        }
        return false;
    }
    public override int GetHashCode()
    {
        int hash = 13;
        hash = hash * 7 + (int)CountryTreeLetter[0];
        hash = hash * 7 + (int)CountryTreeLetter[1];
        hash = hash * 7 + (int)CountryTreeLetter[2];
        return hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后做了:

        var data = e.ParsedData as Country[];
        using (var db = new entities())
        {
            foreach (var item in data.Except(db.Countries))
            {
                db.AddToCountries(item); 
            }
            db.SaveChanges();
        }
Run Code Online (Sandbox Code Playgroud)

Sla*_*uma 24

我会直截了当地说:

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
        foreach(var country in data)
        {
            var countryInDb = db.Countries
                .Where(c => c.Name == country.Name) // or whatever your key is
                .SingleOrDefault();
            if (countryInDb != null)
                db.Countries.ApplyCurrentValues(country);
            else
                db.Countries.AddObject(country);
        }
        db.SaveChanges();
     }
}
Run Code Online (Sandbox Code Playgroud)

我不知道你的应用程序必须经常运行这个或你的世界有多少个国家.但是我觉得这不是你必须考虑复杂的性能优化的地方.

编辑

只发出一个查询的替代方法:

void Method(object sender, DocumentLoadedEvent e)
{
    var data = e.ParsedData as Country[];
    using(var db = new DataContractEntities)
    {
        var names = data.Select(c => c.Name);
        var countriesInDb = db.Countries
            .Where(c => names.Contains(c.Name))
            .ToList(); // single DB query
        foreach(var country in data)
        {
            var countryInDb = countriesInDb
                .SingleOrDefault(c => c.Name == country.Name); // runs in memory
            if (countryInDb != null)
                db.Countries.ApplyCurrentValues(country);
            else
                db.Countries.AddObject(country);
        }
        db.SaveChanges();
     }
}
Run Code Online (Sandbox Code Playgroud)

  • @rudimenter:单个`SaveChanges`调用是一个事务,因此是原子的.我认为问题更多的是如果这些国家在阅读时被锁定,但我不知道这个问题的答案. (2认同)

Gáb*_*bor 9

使用以后的EF版本的现代形式将是:

context.Entry(record).State = (AlreadyExists ? EntityState.Modified : EntityState.Added);
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

AlreadyExists 可以来自检查密钥或查询数据库以查看该项目是否已存在.

  • 你的解决方案很有趣.您能否提供更多背景或参考完整实施这种"现代形式"?我真的很感激! (3认同)