简体   繁体   English

C#,实体框架,自增

[英]C#, entity framework, auto increment

I'm learning Entity Framework under VC# 2010.我正在 VC# 2010 下学习实体框架。

I have created a simple table for learning purposes, one of the fields is "id" type integer, identity set to true.我为学习目的创建了一个简单的表,其中一个字段是“id”类型的整数,identity 设置为 true。 I've generated Entity Data Model from that table and connected it with dataGridView.我已经从该表生成了实体数据模型并将其与 dataGridView 连接起来。 The problem is that it doesn't auto increment - each inserted row wants to be id=0 (which is impossible of course, since id must be unique)问题是它不会自动递增 - 每个插入的行都希望 id=0 (这当然是不可能的,因为 id 必须是唯一的)

What am I doing wrong?我究竟做错了什么? How should I configure EF or the SQL db itself?我应该如何配置 EF 或 SQL 数据库本身?

Check in your EDMX model, that the autoincrement field's StoreGeneratedPattern attribute is set to "Identity".检查您的 EDMX 模型,是否将自动增量字段的 StoreGeneratedPattern 属性设置为“身份”。 In this way, EF knows that the autonumbers are handled by the DB.通过这种方式,EF 知道自动编号由 DB 处理。

Here this is explained better: Autonumber with Entity Framework这里有更好的解释: Autonumber with Entity Framework

The identity isn't set and incremented just by adding to the entity set... The entity isn't actually saved to the db until you call context.SaveChanges()...身份不是通过添加到实体集来设置和递增的......在您调用 context.SaveChanges() 之前,实体实际上并未保存到数据库中......

db.AddToUserSet(user);//Added to EF entity collection
db.SaveChanges();//INSERT executed in db, Identity set and incremented.

I had similar issues, which occurred in EF6 (did work in EF4 without transactions, EF 4 used implicit transactions with the right scope).我有类似的问题,发生在 EF6 中(确实在没有事务的 EF4 中工作,EF 4 使用了具有正确范围的隐式事务)。

Just creating a new entity and saving it did not help in my case (see the comments of the other answers, they had similar issues with using dc.SaveChanges() only to auto-update).只是创建一个新实体并保存它对我的情况没有帮助(请参阅其他答案的评论,他们在使用dc.SaveChanges()仅自动更新时遇到了类似的问题)。

Consider the following code ( CustomerId is the primary key with auto-increment):考虑以下代码( CustomerId是具有自动增量的主键):

public void UpdateCustomer(string strCustomerName, string strDescription)
{
  using (var transaction = CreateTransactionScope())
  {
    MyCustomer tbl=null;
    Func<MyCustomer, bool> selectByName=(i => i.CustomerName.Equals(strCustomerName));
    var doesRecordExistAlready = dc.MyCustomers.Any(selectByName); 
    if (doesRecordExistAlready) 
    {
        // Updating
        tbl=dc.MyCustomers.Where(selectByName).FirstOrDefault();        
        tbl.Description=strDescription;
    }
    else
    {
        // Inserting
        tbl=new MyCustomer(); 
        var maxItem=
           dc.MyCustomers.OrderByDescending(i => i.CustomerId).FirstOrDefault();
        var newID = maxItem==null ? 1 : maxItem.CustomerId+1;
        tbl.CustomerId=newID;
        tbl.CustomerName=strCustomerName; 
        tbl.Description=strDescription;
        dc.MyCustomers.AddObject(tbl);      
    }
    dc.SaveChanges(); // save all changes consistently          
    transaction.Complete(); // commit
  }
}

And the helper function to create the right transaction context is:创建正确事务上下文的辅助函数是:

// creates the right transaction scope
public static System.Transactions.TransactionScope CreateTransactionScope() 
    // needs to add ref: System.Transactions
 { 
    var transactionOptions = new TransactionOptions 
    { 
        IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted,
        Timeout = new TimeSpan(0,0,10,0,0) //assume 10 min is the timeout time
    }; 
    var scopeOption=TransactionScopeOption.RequiresNew;
    var scope = new System.Transactions.TransactionScope(scopeOption, 
               transactionOptions); 
    return scope;
} 

The trick is here, to allow reading uncommitted - hence you can query the max ID and add 1 to id.诀窍就在这里,允许读取未提交 - 因此您可以查询最大 ID 并将 1 添加到 id。 What I wasn't able to achieve is to let SQL server generate the ID automatically, because EF doesn't allow to omit the CustomerId upon creation.我无法实现的是让 SQL 服务器自动生成 ID,因为 EF 不允许在创建时省略CustomerId

To read more about transaction scope, look here.要阅读有关事务范围的更多信息,请查看此处。

Be sure you're saving your Entities back to the database before you try to read the auto-incremented Id value.在尝试读取自动递增的 Id 值之前,请确保将实体保存回数据库。

Your Id won't be set by auto-increment until the first time it is actually saved to the database.您的 ID 不会通过自动递增设置,直到第一次实际保存到数据库中。

Yes.是的。 LINQ to SQL behaves the same way. LINQ to SQL 的行为方式相同。 The id will not be set until it is saved to the database.在将 id 保存到数据库之前,不会设置该 id。 Until you do, all the ids will be zero (as you've already seen).在您这样做之前,所有的 id 都将为零(正如您已经看到的)。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM