EF Core 更新现有实体

Rob*_*abe 2 c# entity-framework-core .net-6.0

我正在使用 EF Core 和 .NET 6,我想将一个实体更新插入到表中 - 这是一个相当简单的问题。

我有以下代码:

var countries = GetCountries();

using (var scope = scopeFactory.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

    foreach (var c in countries)
    {
        // check if the country already exists.
        var exists = dbContext.Countries.Where(d => d.Id == c.Id).FirstOrDefault();

        // if already exists - update (rather than add).
        if (exists != null) 
        {
            exists.Name = c.Name;
            exists.DisplayName = c.DisplayName;
            ... // omitted other prop updates.

            dbContext.Countries.Update(exists);
        } 
        else
        {
            dbContext.Countries.Add(c);
        }
    }

    await dbContext.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)

我想知道 - 是否有一种更有效的更新方法,无需手动查找然后更新(它的性能不是很好)。

最好,我希望MergeEF Core 中有一种方法,但找不到任何有用的东西(这是免费的......)。而不是以这种方式进行手动查找和更新。

我可能在这里遗漏了一些非常明显的东西 - 感谢您提前提供的任何指示!

Svy*_*liv 5

EF Core 没有Merge或类似的 Upsert。您可以通过批量选择现有项目来提高查询性能。另外,您不需要调用Update,只需更改属性即可。

var countries = GetCountries();

using (var scope = scopeFactory.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

    var countyIds = countries.Select(c => c.Id);
    var existing = (await dbContext.Countries.Where(d => countyIds.Contains(d.Id))
        .ToListAsync())
        .ToDictionary(c => c.Id);

    foreach (var c in countries)
    {
        // check if the country already exists.

        if (existing.TryGetValue(c.Id, out var toUpdate))
        {
            // if already exists - update (rather than add).
            toUpdate.Name = c.Name;
            toUpdate.DisplayName = c.DisplayName;
            ... // omitted other prop updates.
        } 
        else
        {
            dbContext.Countries.Add(c);
        }
    }

    await dbContext.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)