Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF4.1 DBContext:在一个Save()函数中插入/更新,不带标识PK_C#_Entity Framework_Entity Framework 4_Primary Key - Fatal编程技术网

C# EF4.1 DBContext:在一个Save()函数中插入/更新,不带标识PK

C# EF4.1 DBContext:在一个Save()函数中插入/更新,不带标识PK,c#,entity-framework,entity-framework-4,primary-key,C#,Entity Framework,Entity Framework 4,Primary Key,我有一个streets表,它有两个字符串列的组合作为主键,分别是postalcode和streetcode 对于EF4.1和DBContext,我想编写一个“Save”方法,然后获取一条街道(以未连接状态进入),检查它是否已经存在于数据库中。如果有,则发布更新;如果没有,则发布插入 仅供参考,保存这些街道的应用程序正在从文本文件中读取并保存这些街道(该文件中有数万条“街道线”) 我现在想到的是: public void Save(Street street) {

我有一个streets表,它有两个字符串列的组合作为主键,分别是postalcode和streetcode

对于EF4.1和DBContext,我想编写一个“Save”方法,然后获取一条街道(以未连接状态进入),检查它是否已经存在于数据库中。如果有,则发布更新;如果没有,则发布插入

仅供参考,保存这些街道的应用程序正在从文本文件中读取并保存这些街道(该文件中有数万条“街道线”)

我现在想到的是:

    public void Save(Street street)
    {
        var existingStreet = (
                                from s in streetContext.Streets
                                where s.PostalCode.Equals(street.PostalCode)
                                && s.StreetCode.Equals(street.StreetCode)
                                select s
                             ).FirstOrDefault();

        if (existingStreet != null)
            this.streetContext.Entry(street).State = System.Data.EntityState.Modified;
        else
            this.streetContext.Entry(street).State = System.Data.EntityState.Added;

        this.streetContext.SaveChanges();
    }
这是好的做法吗?这里的表演怎么样?因为对于每一条街道,它都会首先往返到db,看看它是否存在

尝试插入street(state=added)并捕获任何PK违规不是更好的性能明智之举吗?在catch块中,我可以将状态更改为modified并再次调用SaveChanges()。或者这不是一个好的做法

有什么建议吗


谢谢

选择所有街道,然后为每个循环创建一个比较和更改状态的循环。循环完成后,调用saveChanges。这样,您只需对数据库进行几次调用,而不是数千次调用。如果数据库中已经存在street,则您的代码必须导致异常,因为您将从上下文加载它,然后尝试将另一个具有相同主键的实例附加到同一上下文实例

如果确实必须这样做,请使用以下代码:

public void Save(Street street)
{
    string postalCode = street.PostalCode;
    string streetCode = steet.StreetCode;
    bool existingStreet = streetContext.Streets.Any(s =>
                            s.PostalCode == postalCode
                            && s.StreetCode = steetCode);

    if (existingStreet)
        streetContext.Entry(street).State = System.Data.EntityState.Modified;
    else
        streetContext.Entry(street).State = System.Data.EntityState.Added;

    streetContext.SaveChanges();
}

无论如何,在高度并发的系统中,它仍然不是可靠的解决方案,因为其他线程可以在您检查和后续插入之间插入相同的街道。

感谢您的回复,但没有一个是真正令人满意的,所以我做了更多的研究,并重新编写了这样的方法,满足了我的需要

ps:重命名了方法to Import(),因为我发现用于从外部源(如我的示例中的文本文件)批量导入实体的方法的名称更合适

ps2:我知道捕捉异常并让它安静地死去不是最好的做法,但在我的特殊情况下,我没有必要对它做任何事情。它只是一种发现数据库中已经存在该行的方法

public void Import(Street street)
{
        try
        {
            this.streetContext.Entry(street).State = System.Data.EntityState.Added;

            this.streetContext.SaveChanges();
        }
        catch (System.Data.Entity.Infrastructure.DbUpdateException dbUex)
        {
            this.streetContext.Entry(street).State = System.Data.EntityState.Modified;

            this.streetContext.SaveChanges();
        }
        finally
        {
            ((IObjectContextAdapter)this.streetContext).ObjectContext.Detach(street);
        }
} 

谢谢,但我认为从性能角度来看,一次在内存中加载20K street实体并不是一个真正的选择