Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Работа с идентификаторами в дизайне объекта сущности

Автор вопроса: DEHAASОтветов: 3

Какое-то время я думал о том, как работать с объектами, которым в базе данных присвоены идентификаторы.

Типичный объект, представляющий сущность таблицы, может выглядеть так:

public class Test
{
    public int Id { get; private set; }
    public string Something { get; set; }
}

Предположим, мы хотели бы использовать этот объект для вставки, извлечения и обновления объектов в базе данных. Что касается получения и обновления, у нас нет проблем, так как поле Id всегда имеет значение.

Однако, если мы хотим вставить новый объект типа Test в базу данных, поле Id все равно должно иметь значение. Мы могли бы просто использовать "0", поскольку он вряд ли будет использоваться в качестве ключа базы данных, но на самом деле это не очень хорошая конструкция.

Аналогичным образом, если мы инвертируем ситуацию и сделаем свойство Id допускающим значение NULL, мы могли бы использовать NULL для объектов, которым база данных еще не присвоила идентификатор. Однако теперь возможно, что объект, полученный из базы данных, не имеет идентификатора (как это допускается конструкцией класса, но не конструкцией базы данных).

Есть какие-нибудь хорошие идеи о том, как создать хороший дизайн для этой проблемы?

  • невозможно получить объект без идентификатора, если он был извлечен из базы данных .. когда вы вставляете его, он немедленно получит идентификатор (если у вас нет какой-то действительно странной базы данных) xs0 17.05.2011
  • @ xs0 Очевидно. Однако, если строго смотреть на определение типа объекта, это возможно. DEHAAS 17.05.2011
  • Ну, вы в своем вопросе говорите обратное .. Но что вы хотите делать с этими объектами? Пока вы не объясните, какие операции с ними будут делать, непонятно, в чем проблема. xs0 17.05.2011
  • Вы используете Entity Framework или имели в виду сущность в общем смысле? Tim 17.05.2011
  • Я имею в виду сущность в общем смысле, хотя проблема, очевидно, существует и при использовании Entity Framework. DEHAAS 17.05.2011

databaseentityclass-design

Ответы

Ответ 1 · рейтинг 3 · k.m

Если вы рассматриваете id как способ идентификации / предоставления уникальности объекту в вашем приложении, это должно обрабатываться базой данных (если, конечно, у вас есть другие способы присвоения идентификаторов объектам).

Если это не так (например, это свойство объекта, обусловленное бизнес-потребностями) - то, является ли 0 допустимым / хорошим проектным значением или нет, зависит исключительно от этих бизнес-потребностей. Является ли 0 допустимым значением, скажем, с точки зрения конечного пользователя?

Вы всегда можете поместить свойства объекта в отдельный класс, если считаете, что иметь объекты без ids, установленных в вашем приложении, проблематично. Вы будете использовать такой класс, по сути, только для переноса параметров для еще объекта (процесс создания завершается вставкой в ​​базу данных). Как только объект будет вставлен, назначен идентификатор и прочее - вы можете работать со своим обычным объектом. Будет ли ваш пользователь "Ох, хватит! Что это?" или "Хорошо ... Я знаю, что делать", когда к нему обращается id = 0?

Изменить

Этот вопрос (а точнее мой ответ о параметрах упаковки) напомнил мне факт, который когда-то меня удивил. Когда ребенок рождается, он не существует в системе до тех пор, пока родители официально не зарегистрируют его, и ей не будет присвоен личный идентификационный номер. Так что технически, без id - ребенка не существует (по крайней мере, с системной точки зрения), даже несмотря на то, что все знают, что она родилась и все такое. То же самое и с базой данных / вашим приложением - объект без id (тот, который база данных не может идентифицировать) не существует - это просто набор параметров. Немного странно, но я надеюсь, что моя точка зрения ясна :)

Ответ 2 · рейтинг 3 · Jeffrey L Whitledge

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

Одна ловушка, на которую следует обратить внимание, - это использование идентификатора для определения отношения равенства (например, для генерации хэш-кодов для словаря). Это нужно делать только для ненулевых идентификаторов. Для проверки равенства с двумя нулевыми идентификаторами может использоваться эталонное равенство.

Однако, поскольку не сохраненные объекты могут изменить свой идентификатор в какой-то момент в будущем, очень важно, чтобы такие объекты никогда не сохранялись в Словаре. Или, по крайней мере, такие элементы должны быть удалены из любых словарей перед сохранением, а затем восстановлены после этого с использованием нового идентификатора.

С одной лишь оговоркой, этот дизайн должен работать нормально.

public class Test : IEquatable<Test>
{
    /// <summary>
    /// The unique identifier for this Test entity, or zero if this
    /// Test entity has not yet been serialized to the database.
    /// </summary>
    public int Id { get; private set; }

    public string Something { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as Test);
    }

    public bool Equals(Test other)
    {
        if (other == null)
            return false;
        // Distinct entities may exist with the Id value of zero.
        if (Id == 0)
            return object.ReferenceEquals(this, other);
        return Id == other.Id;
    }

    /// <summary>
    /// Gets a hash code for this Test entity. Warning: an instance with
    /// an Id of zero will change its identity when saved to the DB. Use with care.
    /// </summary>
    /// <returns>The hash code.</returns>
    public override int GetHashCode()
    {
        return Id;
    }
}

Ответ 3 · рейтинг 1 · FIre Panda

Итак, у вас есть класс, который содержит идентификатор таблицы базы данных в виде поля, поэтому в случае извлечения / удаления и обновления идентификатор вашей сущности выравнивается с идентификатором записи в базе данных. В случае вставки вы можете получить идентификационное значение только что вставленной записи и обновить свой объект этим значением. Таким образом, у вас могут быть отдельные процедуры хранения для вставки / обновления / извлечения и удаления. SP вставки может вернуть вам идентификатор только что вставленной записи как out parameter. Надеюсь, я отвечу на твой вопрос.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы