С#, структура сущности, автоматическое увеличение
Я изучаю Entity Framework под VС# 2010.
Я создал простую таблицу для учебных целей, одно из полей - целое число id, а идентификатор - true. Я создал модель данных сущности из этой таблицы и связал ее с dataGridView. Проблема в том, что он не увеличивается автоматически - каждая вставленная строка хочет быть id = 0 (что, конечно, невозможно, так как id должен быть уникальным)
Что я делаю неправильно? Как мне настроить EF или сам SQL db?
Ответы
Ответ 1
Проверьте в своей модели EDMX, что для поля автоинкремента StoreGeneratedPattern установлено значение "Identity". Таким образом, EF знает, что autonumbers обрабатываются БД.
Здесь это объясняется лучше: Автономный номер с инфраструктурой Entity
Ответ 2
Идентификатор не задается и увеличивается только путем добавления в набор объектов...
Сущность фактически не сохраняется в db, пока вы не вызовете context.SaveChanges()...
db.AddToUserSet(user);//Added to EF entity collection
db.SaveChanges();//INSERT executed in db, Identity set and incremented.
Ответ 3
Убедитесь, что вы сохраняете свои объекты обратно в базу данных, прежде чем пытаться прочитать значение с автоматическим приращением идентификатора.
Ваш идентификатор не будет установлен с помощью автоматического инкремента до момента его фактического сохранения в базе данных.
Ответ 4
Да. LINQ to SQL ведет себя одинаково. Идентификатор не будет установлен до тех пор, пока он не будет сохранен в базе данных. Пока вы это сделаете, все идентификаторы будут равны нулю (как вы уже видели).
Ответ 5
У меня были аналогичные проблемы, которые произошли в EF6 (работали в EF4 без транзакций, EF 4 использовали неявные транзакции с правильной областью).
Просто создание нового объекта и его сохранение не помогли в моем случае (см. комментарии к другим ответам, у них были аналогичные проблемы с использованием 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;
}
Трюк здесь, чтобы разрешить чтение uncommitted - следовательно, вы можете запросить max ID и добавить 1 к id. То, чего я не смог достичь, - позволить SQL-серверу генерировать идентификатор автоматически, потому что EF позволяет мне не пропускать CustomerId
при создании.
Чтобы узнать больше о области транзакций, посмотреть здесь.