简体   繁体   English

使用复合键在 Microsoft.EntityFrameworkCore.SqlServer 5.0.8 C# 中进行更新

[英]Upsert in Microsoft.EntityFrameworkCore.SqlServer 5.0.8 C# with a composite key

I have a composite key ( sku ( nvarchar /string value) and quantity ( int value)) and I want to do an upsert in Microsoft.EntityFrameworkCore.SqlServer 5.0.8 using C#.我有一个复合键( skunvarchar /string 值)和quantityint值)),我想在 Microsoft.EntityFrameworkCore.SqlServer 5.0.8 中使用 C# 做一个 upsert。

The AddOrUpdate call is missing from the context - not that we're supposed to be using that anyway, since it's primarily meant for migrations.上下文中缺少AddOrUpdate调用 - 并不是说​​我们无论如何都应该使用它,因为它主要用于迁移。

How do I accomplish this?我该如何实现?

Having a composite key means (as a compare to a single surrogate-key-primary-key)......it is still a "match and find or not find" proposition.拥有一个复合键意味着(作为与单个代理键-主键的比较)......它仍然是一个“匹配并找到或不找到”的命题。

First, the setup.首先,设置。

https://docs.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#configuring-a-primary-key https://docs.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#configuring-a-primary-key

You can also configure multiple properties to be the key of an entity您还可以将多个属性配置为实体的键

  • this is known as a composite key.这称为复合键。 Composite keys can only be configured using the Fluent API;复合键只能使用 Fluent API 进行配置; conventions will never set up a composite key, and you can not use Data Annotations to configure one.约定永远不会设置复合键,并且您不能使用数据注释来配置一个。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .HasKey(c => new { c.State, c.LicensePlate });
}

Then you will Add items to your dbContext.然后,您将向 dbContext 添加项目。 (like adding object(s) to a collection) (例如将对象添加到集合中)

for each CarEntity currentCar : myCarCollection)
{
      /* this code may not work for the future copy-pasters out there..i'm building up a little, see "WHERE IN" later in this answer */
        this.myEntityDbContext.MyCars.Add(currentCar);
}

Then you will call然后你会打电话

await this.myEntityDbContext.SaveChangesAsync(token);

(or the sync version .SaveChanges) (或同步版本 .SaveChanges)

EF ~~may be able (but probably not) to find existing-matches (and update existing) or insert new ones. EF ~~也许能够(但可能不能)找到现有匹配(并更新现有)或插入新匹配。 And it depends on the state of your myDbContext at the moment of impact.这取决于您的 myDbContext 在影响时刻的状态。 (Again, i'm trying to build this up a little bit with talking about it, instead of just giving a copy/paste answer...you gotta try to understand how EF is working a little...to get better at debugging it) (同样,我试图通过谈论它来建立这一点,而不是仅仅给出复制/粘贴答案......你必须尝试了解 EF 是如何工作的......以便更好地进行调试它)

with the M$ example.以 M$ 为例。

if the database already has a如果数据库已经有

c.State = "VA", c.LicensePlate = "2222-2222" c.State = "VA", c.LicensePlate = "2222-2222"

but does not have但没有

c.State = "WV", c.LicensePlate = "3333-3333" c.State = "WV", c.LicensePlate = "3333-3333"

Now, and you add both of these to your myDbContext (the "currentCar" code above) and then call "SaveChangesAsync"....that MIGHT work.现在,您将这两个添加到 myDbContext(上面的“currentCar”代码),然后调用“SaveChangesAsync”......这可能会起作用。 But it will probably fail.但它可能会失败。 That's ok.没关系。

Here is one "trick".这是一个“技巧”。 (it may not be the only one) (它可能不是唯一的)

You need to get the existing items (where VA/2222-2222 already exists) INTO the myDbContext.您需要将现有项目(其中 VA/2222-2222 已经存在)放入 myDbContext。

So before you do the MyCars.add....所以在你做 MyCars.add 之前......

call the EF equivalent of (rdbms WHERE IN ) ( see Entity Framework Core - IN clause equivalent )调用 (rdbms WHERE IN ) 的 EF 等效项(请参阅Entity Framework Core-IN 子句等效项

and the values you try check against the EF version of "WHERE IN".....will be both combinations of the "Car".并且您尝试对照“WHERE IN”的 EF 版本检查的值......将是“Car”的两个组合。

I just read one of the comments.我刚刚阅读了其中一条评论。 Yes, that is very helpful.是的,这很有帮助。 For clarity, this link: Update Row if it Exists Else Insert Logic with Entity Framework为清楚起见,此链接: 更新行,如果它存在,则使用实体框架插入逻辑

That link is saying "how do i check for exist/not-exists IN THE DBCONTEXT) .. but for a SINGLE-BOOK. The where-exists stuff above is about getting the dbcontext loaded for several (cars,books,whatever).该链接是说“我如何检查 DBCONTEXT 中的存在/不存在)......但是对于单本。上面存在的东西是关于为几个(汽车,书籍,任何东西)加载 dbcontext。

Now, you can do some checking on whether to .Add (a Car) to the myDbContext, or "change some properties" of an existing.现在,您可以检查是否将(汽车)添加到 myDbContext 或“更改现有的某些属性”。 *** ***

But as the other link points out, you're gonna check for the values (the VA and the NC and the 2222-2222 and the 3333-3333), you gonna check the dbContext (items)但是正如另一个链接指出的那样,您将检查值(VA 和 NC 以及 2222-2222 和 3333-3333),您将检查 dbContext(项目)

Let me explain that answer's "trick".让我解释一下这个答案的“技巧”。

context.Entry(blog).State = blog.BlogId == 0 ? 
                               EntityState.Added : 
                               EntityState.Modified; 
             

That is an old-"fairly standard" trick of using 0 as the "do i already exist or not".这是使用 0 作为“我是否已经存在”的古老“相当标准”的技巧。 with the "Car" from above, you don't have a single-surrogate-usually-primarykey thing like "BlogId".使用上面的“汽车”,您没有像“BlogId”这样的单一代理通常是主键。 with the car, you have 2 parts.对于汽车,您有 2 个部分。 so you'll have to check the myDbContext using the n-parts-of-the-compound-key to determine this.所以你必须使用 n-parts-of-the-compound-key 检查 myDbContext 来确定这一点。 it'll take a little experimentation to tweak your code.调整您的代码需要一些实验。

You will have to be aware if your context is long-lived (like a winforms desktop app) or your context is short-lived (like a rest-api).您必须知道您的上下文是长期存在的(如 winforms 桌面应用程序)还是短期的(如 rest-api)。

But that is a much deeper question.但这是一个更深层次的问题。 Here is a hint.这是一个提示。

https://docs.microsoft.com/en-us/ef/core/querying/tracking https://docs.microsoft.com/en-us/ef/core/querying/tracking


Then you gotta consider how hard your system is getting hit.然后你必须考虑你的系统受到多大程度的打击。 This could be a race-condition in a high hit system.这可能是高命中系统中的竞争条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Microsoft.EntityFrameworkCore.SqlServer依赖关系无法解决 - Microsoft.EntityFrameworkCore.SqlServer dependency could not be resolved 无法找到无法找到包“Microsoft.EntityFrameworkCore.SqlServer” - Unable to find Unable to find package 'Microsoft.EntityFrameworkCore.SqlServer' Nuget 找不到包(Microsoft.EntityFrameworkCore.SqlServer) - Nuget pacakage (Microsoft.EntityFrameworkCore.SqlServer) can not found Microsoft.EntityFrameworkCore.SqlServer - 数据库未在 context.Database.Migrate() 上更新; - Microsoft.EntityFrameworkCore.SqlServer - Database not updating on context.Database.Migrate(); 错误 NU1202 Microsoft.EntityFrameworkCore.SqlServer 5.0.0 package 与 net50 不兼容 - Error NU1202 Microsoft.EntityFrameworkCore.SqlServer 5.0.0 package is not compatible with net50 NU1107:Microsoft.EntityFrameworkCore.SqlServer 的 .Net Core 2.1 兼容替代品? - NU1107: .Net Core 2.1-compatible alternatives to Microsoft.EntityFrameworkCore.SqlServer? 用组合键更新? - Upsert with composite key? C#Microsoft.SqlServer参考中的错误 - Error in C# Microsoft.SqlServer reference SQL / C# - UPSERT上的主键错误 - SQL/C# - Primary Key error on UPSERT 在Microsoft.SqlServer.Management.Smo中找不到C#传输 - C# Transfer not found in Microsoft.SqlServer.Management.Smo
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM