Отображение списка <string>в строку с разделителями с помощью Fluent NHibernate - PullRequest
7 голосов
/ 17 ноября 2010

Моя модель выглядит примерно так:

public class Product
{
    public string Name {get; set;}
    public string Description {get; set;}
    public double Price {get; set;}
    public List<string> Features {get; set;}
}

Я хочу, чтобы моя таблица базы данных была плоской - список должен храниться в виде строки с разделителями: Особенность одна | Особенность вторая | Особенность три, например.

При получении из базы данных каждый из этих элементов должен быть помещен обратно в список

.

Возможно ли это?

Ответы [ 3 ]

11 голосов
/ 30 ноября 2010

Я делаю то же самое в моем текущем проекте, только я сохраняю коллекцию перечислений в виде разделенных каналом чисел. Работает так же.

public class Product
{
    protected string _features; //this is where we'll store the pipe-delimited string
    public List<string> Features {
        get
        {
            if(string.IsNullOrEmpty(_features)
                return new List<String>();
            return _features.Split(new[]{"|"}, StringSplitOptions.None).ToList();
        }
        set
        {
            _features = string.Join("|",value);
        }
    }
}

public class ProductMapping : ClassMap<Product>
{
    protected ProductMapping()
    {
        Map(x => x.Features).CustomType(typeof(string)).Access.CamelCaseField(Prefix.Underscore);
    }
}
0 голосов
/ 18 ноября 2010

Я также реализовал нечто подобное для структуры Point3D.Как сказал cdmdotnet, вы в основном хотите реализовать и IUserType, который будет упаковывать / распаковывать компоненты в одну строку с помощью методов NullSafeSet / NullSafeGet.

Возможно, вам также потребуется реализовать метод Equals (), который немного неуловим,Причину лучше всего иллюстрирует пример:

    Product p = session.Load(...);
p.Features.Add("extra feature");
session.Save(p);

Дело в том, что NHibernate при гидратации сохраняет ссылку на p.Features и сравнивает ее со значением p.Features по запросу на сохранение.Для неизменяемых типов свойств это нормально, но в приведенном выше примере эти ссылки идентичны, поэтому эффективное сравнение равно

var x = p.Features;
var changed = Equals(x, x);

Очевидно, стандартная реализация этого всегда будет возвращать false.

Как с этим бороться?Я понятия не имею, что такое лучший метод, но решения следующие:

  • Сделать IUserType.Equals (объект x, объект y) всегда возвращать false.Это заставит пересозданную упакованную строку и вызов базы данных каждый раз при сохранении Продукта, независимо от того, был ли Продукт семантически изменен или нет.Является ли это проблемой, зависит от любого количества факторов (размер / количество объектов Feature, сохраняются ли объекты Product, если они не были изменены, сколько у вас объектов Product и т. Д.).

  • Сделать функции IList и реализовать ChangeAwareList<T> : IList<T>, который может отслеживать изменения (или сохранять копию своего оригинала) в курсе.Реализуйте IUserType.Equals (объект x, объект y), чтобы проверить, являются ли значения x / y ChangeAwareList, и реализуйте необходимую логику, чтобы увидеть, действительно ли список изменился.Это решение, которое я использовал в конце.

  • Возможно, вы могли бы повторно использовать код типа NHibernate GenericListType.В то время, когда я реализовывал предыдущее решение, у меня не было достаточно опыта, чтобы попробовать это.

Если у вас есть опыт работы с NHibernate, надеюсь, это поможет вам начать работу,Если нет, дайте мне знать, и я постараюсь составить более подробное решение.

0 голосов
/ 18 ноября 2010

Я реализовал нечто подобное для типа данных набора MySql, который представляет собой разделенный запятыми список в БД, но список строк в модели сущностей.Он включал использование пользовательского типа данных в NHibernate, основанного на классе PrimitiveType.Вы подключаете это, используя сопоставления и метод .CustomType () на карте.

Если вы хотите, я могу отправить вам фрагмент кода для пользовательского класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...