GUID или ключ объекта int с SQL Compact/EF4?

Это продолжение более раннего вопроса, который я разместил о ключах сущностей EF4 с помощью SQL Compact. SQL Compact не позволяет создавать ключи идентификации, сгенерированные сервером, поэтому мне остается создавать собственные ключи по мере добавления объектов в файл ObjectContext. Моим первым выбором был бы целочисленный ключ, а предыдущий ответ был связан с сообщение в блоге, в котором показан метод расширения, использующий оператор Max с выражением селектора для поиска следующего доступного ключа:

public static TResult NextId<TSource, TResult>(this ObjectSet<TSource> table,  Expression<Func<TSource, TResult>> selector) 
    where TSource : class
{
    TResult lastId = table.Any() ? table.Max(selector) : default(TResult);

    if (lastId is int)
    {
        lastId = (TResult)(object)(((int)(object)lastId) + 1);
    }

    return lastId;
}

Вот мой взгляд на метод расширения: он будет работать нормально, если ObjectContext, с которым я работаю, имеет нефильтрованный набор сущностей. В этом случае ObjectContext будет содержать все строки из таблицы данных, и я получу точный результат. Но если набор сущностей является результатом фильтра запроса, метод вернет последний ключ сущности в отфильтрованном наборе сущностей, который не обязательно будет последним ключом в таблице данных. Поэтому я думаю, что метод расширения не будет работать.

На данный момент очевидным решением кажется простое использование GUID в качестве ключа сущности. Таким образом, мне нужно только вызвать метод Guid.NewGuid(), чтобы установить свойство ID, прежде чем я добавлю новый объект в свой ObjectContext.

Вот мой вопрос: есть ли простой способ получить последний первичный ключ в хранилище данных из EF4 (без необходимости создания второго ObjectContext для этой цели)? Любая другая причина не выбирать легкий путь и просто использовать GUID? Спасибо за вашу помощь.


person David Veeneman    schedule 20.03.2010    source источник
comment
Подход, который вы показываете, вообще не выглядит потокобезопасным! Что мешает двум потокам получить один и тот же идентификатор?   -  person Ian Mercer    schedule 26.03.2010
comment
Для меня это не проблема — я использую SQL CE только для однопользовательских приложений и генерирую записи только в одном потоке. Однако хороший момент, если кто-то хочет создать многопоточную запись в SQL CE.   -  person David Veeneman    schedule 26.03.2010


Ответы (4)


В итоге я пошел с GUID.

  • Проблемы размера/производительности не являются критическими (или даже заметными) для SQL Compact, поскольку это локальная однопользовательская система. Это не похоже на то, что приложение будет управлять системой бронирования авиабилетов.

  • И, по крайней мере, на данный момент кажется, что нет никакого способа обойти ограничение стека SQL Compact/EF4 «без ключей, сгенерированных сервером». Если у кого-то есть умный хак, я все еще открыт для него.

Это не означает, что я буду использовать тот же подход в SQL Server или SQL Express. Я по-прежнему отдаю предпочтение целочисленным ключам, и более крупные братья и сестры SQL Compact позволяют использовать их в сочетании с EF4.

person David Veeneman    schedule 22.03.2010

Используйте руководство. Автоинкремент не поддерживается в Compact Framework с Entity Framework.

Кроме того, если вы когда-нибудь захотите создать приложение, которое использует несколько источников данных, целевые PK развалятся для вас очень и очень быстро.

  • С помощью Guid вы можете просто вызвать Guid.NewGuid(), чтобы получить новый ключ.
  • С int вы должны попасть в базу данных, чтобы получить действительный ключ.

Если вы храните данные в нескольких базах данных, int PK вызовет конфликты.

person user276695    schedule 26.03.2010

То, что я делал для SQL CE раньше, и я предполагаю, что у нас есть одно приложение, обращающееся к базе данных, заключается в том, чтобы вычислить значение MAX при запуске и поместить его в статическую переменную. Теперь вы можете легко передавать последовательные значения, и вы можете очень легко сделать код для их создания потокобезопасным.

person Ian Mercer    schedule 26.03.2010
comment
Я на самом деле рассмотрел этот подход, и он хороший. В итоге я остановился на GUID из-за его простоты. - person David Veeneman; 26.03.2010

Одной из причин, по которой следует избегать Guids, может быть размер = потребление памяти и дискового пространства.

Вы также можете запросить метаданные SQL Compact следующим образом:

ВЫБЕРИТЕ AUTOINC_NEXT ИЗ INFORMATION_SCHEMA.COLUMNS, ГДЕ TABLE_NAME = «Категории» И AUTOINC_NEXT НЕ НУЛЕВОЕ

person ErikEJ    schedule 21.03.2010
comment
Как мне выполнить этот запрос с помощью EF4? - person David Veeneman; 21.03.2010