Я пытаюсь решить дилемму, которая мучила меня последние несколько месяцев.
Моя Мы с коллегами полностью не согласны по технической проблеме, и мне хотелось бы узнать мнение нашего любимого сообщества по этому поводу.
Предпочтительнее ли использовать перечисления (с потенциально атрибутами, такими как «Описание») , или использовать сущности (со свойствами Name и Description)?
В нашей модели предметной области у нас есть много мини-сущностей, которые содержат только Id, Name и Description. В 95% случаев Описание совпадает с Именем.
Для пояснения я возьму один из многих примеров: в нашей сущности Security у нас есть свойство AssetClass. AssetClass имеет статический список значений («Капитал», «Облигация» и т. Д.) И не изменяется из интерфейса или чего-либо еще.
Проблема в том, что вы хотите получить все ценные бумаги вместе с активом. класса "Bond" скажем, NHibernate должен будет присоединиться к таблице AssetClass ... и, учитывая, что AssetClass - не единственное подобное свойство, вы можете представить себе влияние на производительность всех этих объединений.
В нашем коде есть несколько жестко запрограммированных экземпляров AssetClass со всеми соответствующими значениями и идентификаторами (например, Equity с Id 1, Bond с Id 2 и т. Д.), Которые соответствуют тому, что находится в базе данных. :
public partial class AssetClass
{
static public AssetClass Equity = new AssetClass(1, "Equity", "Equity");
static public AssetClass Bond = new AssetClass(2, "Bond", "Bond");
static public AssetClass Future = new AssetClass(3, "Future", "Future");
static public AssetClass SomethingElse = new AssetClass(4, "Something else", "This is something else");
}
Мы также создали специальный тип NHibernate (код ниже, если вам интересно), который позволяет нам избежать NHibernate, выполняющего соединение, путем загрузки этого жестко запрограммированного экземпляра вместо обращения к базе данных для его получения:
using System;
using System.Data;
using System.Data.Common;
using NHibernate.Dialect;
using NHibernate.SqlTypes;
using NHibernate.Type;
namespace MyCompany.Utilities.DomainObjects
{
public abstract class PrimitiveTypeBase<T> : PrimitiveType where T : class, IUniquelyNamed, IIdentifiable
{
private readonly PrimitiveTypeFactory<T> _factory;
public PrimitiveTypeBase() : base(SqlTypeFactory.Int32)
{
_factory = new PrimitiveTypeFactory<T>();
}
public override string Name
{
get { return typeof(T).Name; }
}
public override Type ReturnedClass
{
get { return typeof(T); }
}
public override Type PrimitiveClass
{
get { return typeof (int); }
}
public override object DefaultValue
{
get { return null; }
}
public override void Set(IDbCommand cmd, object value, int index)
{
var type = value as T;
var param = cmd.Parameters[index] as DbParameter;
param.Value = type.Id;
}
public override object Get(IDataReader rs, int index)
{
return GetStaticValue(rs[index]);
}
public override object Get(IDataReader rs, string name)
{
return GetStaticValue(rs[name]);
}
private T GetStaticValue(object val)
{
if (val == null)
{
return (T)DefaultValue;
}
int id = int.Parse(val.ToString());
T entity = _factory.GetById(id); // that returns, by reflection and based on the type T, the static value with the given Id
if (entity == null)
{
throw new InvalidOperationException(string.Format("Could not determine {0} for id {1}", typeof (T).Name, id));
}
return entity;
}
public override object FromStringValue(string xml)
{
return GetStaticValue(xml);
}
public override string ObjectToSQLString(object value, Dialect dialect)
{
var type = value as T;
return type.Id.ToString();
}
}
}
Замена этих сущностей на перечисления, и если нам когда-нибудь понадобится поле описания, используйте атрибут. У нас также может быть ограничение на базу данных, чтобы убедиться, что вы не можете хранить случайные значения, не соответствующие перечислению.
А что ВЫ думаете?