我正在学习使用 VC# 2010 下的 Entity Framework。
我创建了一个简单的表格,用于学习目的,其中一个字段是“id”,类型为整数,标识设置为 true。我从该表生成了实体数据模型,并将其与 dataGridView 连接起来。问题是它不会自动递增 - 每个插入的行都希望 id=0(这显然是不可能的,因为 id 必须唯一)
我做错了什么?我应该如何配置 EF 或 SQL 数据库本身?
我正在学习使用 VC# 2010 下的 Entity Framework。
我创建了一个简单的表格,用于学习目的,其中一个字段是“id”,类型为整数,标识设置为 true。我从该表生成了实体数据模型,并将其与 dataGridView 连接起来。问题是它不会自动递增 - 每个插入的行都希望 id=0(这显然是不可能的,因为 id 必须唯一)
我做错了什么?我应该如何配置 EF 或 SQL 数据库本身?
检查你的EDMX模型,确保自增字段的StoreGeneratedPattern属性设置为"Identity"。这样,EF就知道自动编号是由数据库处理的。
这里有更好的解释:使用Entity Framework进行自动编号
仅通过将实体添加到实体集中并不会设置和递增标识符...直到调用context.SaveChanges()时,实体才被真正保存到数据库中...
db.AddToUserSet(user);//Added to EF entity collection
db.SaveChanges();//INSERT executed in db, Identity set and incremented.
我曾经遇到过类似的问题,这个问题出现在EF6中(在没有事务的情况下,EF4可以工作,因为EF4使用了正确范围的隐式事务)。
仅仅创建一个新实体并保存它并不能解决我的问题(请看其他答案的评论,他们也有类似的问题,只使用dc.SaveChanges()
进行自动更新)。
请考虑以下代码(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
}
}
创建正确的事务上下文的辅助函数为:
// 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;
}
关键在于允许读取未提交的内容 - 因此您可以查询最大ID并将1添加到ID。我无法实现的是让SQL服务器自动生成ID,因为EF不允许在创建时省略CustomerId
。
要了解有关事务范围的更多信息,请查看此处。
在尝试读取自增Id值之前,请确保将实体保存回数据库。
只有在第一次保存到数据库时,Id才会被自动递增设置。
是的,LINQ to SQL 的行为也是如此。在保存到数据库之前,id 不会被设置。在此之前,所有的 id 都将为零(正如你已经看到的那样)。