2010-11-17 6 views
6

moim modelu wygląda mniej więcej tak:Mapowanie Lista <string> do wyznaczonego ciągiem z Fluent NHibernate

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

chcę mój tabeli bazy danych musi być płaska - lista powinna być przechowywana w postaci ograniczonego wyrażenie: Feature jeden | Feature two | Feature three na przykład.

Kiedy pobierane z db, należy umieścić każdy z tych elementów z powrotem do listy

Czy to możliwe?

Odpowiedz

9

Robię to samo w moim bieżącym projekcie, tylko utrzymuję kolekcję wyliczeń jako liczb rozdzielanych rurami. Działa to w ten sam sposób.

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); 
    } 
} 
+1

Podoba mi się twoje rozwiązanie, ale chciałbym zadać pytanie. Narażasz właściwość 'Features' jako' List' sugerującą, że można nią manipulować używając 'Add' i' Remove' itd. Czy twoja lista naprawdę to robi. Jeśli nie, dlaczego nie wystawić "IEnountable"? –

+0

Bardzo dobry punkt - to by miało więcej sensu. Używałbym metod pomocniczych do dodawania i usuwania. – DanB

+0

@DanB, przepraszam za wykopanie starego posta: Stwierdzasz, że nadal przechowujesz kolekcję wyliczeń, ale nie jest dla mnie jasne, skąd bierzesz tę kolekcję do tego rozwiązania. Tylko dla odniesienia, możesz sprawdzić ten post, aby zobaczyć co robię: http://stackoverflow.com/questions/14288249/want-to-save-selected-ie-more-than-1-enums- is- string- z-nhibernate – REMESQ

0

Zaimplementowałem coś podobnego dla typu danych zestawu MySql, który jest listą rozdzielaną przecinkami w bazie danych, ale listą ciągów w modelu encji. Wymagało to użycia niestandardowego typu danych w NHibernate, w oparciu o klasę PrimitiveType. Podłączono to za pomocą mapowań i metody .CustomType < CustomType>() na mapie.

Jeśli chcesz, mogę przesłać kod snipet dla niestandardowej klasy.

0

Zaimplementowałam również coś podobnego do struktury Point3D. Jako że cdmdotnet powiedział, że zasadniczo chcesz zaimplementować i IUserType, który spakie/rozpakuje funkcje w jeden ciąg za pomocą metod NullSafeSet/NullSafeGet.

Może być również konieczne zastosowanie metody Equals(), która jest nieco subtelna. Powodem, najlepiej ilustruje przykład:

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

Chodzi o to, NHibernate po sklepach hydratacji odniesienie do p.Features i porównuje ją z wartością p.Features momencie żądania składowania. Dla niezmiennych typów własności to jest w porządku, ale w powyższym przykładzie, te odniesienia są identyczne, więc skuteczne porównanie jest

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

Oczywiście standardem realizacja będzie zawsze return false.

Jak należy sobie z tym poradzić? Nie mam pojęcia, co najlepsze praktyki jest, ale rozwiązania są:

  • Bądź IUserType.Equals (obiekt x, y obiekt) zawsze return false. Zmusi to do przebudowania spakowanego łańcucha i wywołania bazy danych za każdym razem, gdy Produkt zostanie zapisany, bez względu na to, czy Produkt został zmieniony semantycznie, czy też nie. To, czy jest to problem, zależy od wielu czynników (wielkość/liczba obiektów Feature, czy obiekty produktu są zapisywane, gdy nie są zmienione, ile obiektów produktu masz itp.).

  • Twórz funkcje IList i wdrażaj ChangeAwareList<T> : IList<T>, który jest w stanie śledzić zmiany (lub zachować kopię oryginału). Zaimplementuj IUserType.Equals (obiekt x, obiekt y), aby sprawdzić, czy x/y to ChangeAwareList i wdrożyć niezbędną logikę, aby sprawdzić, czy lista naprawdę się zmieniła. To jest rozwiązanie, które podjąłem w końcu.

  • Być może można ponownie użyć kodu z typu NHibernate GenericListType. W tym czasie zaimplementowałem poprzednie rozwiązanie, nie miałem wystarczającego doświadczenia, aby się na to zdobyć.

Jeśli masz jakieś wcześniejsze doświadczenia z NHibernate, mam nadzieję, że powinno to pomóc Ci zacząć. Jeśli nie daj mi znać, a ja postaram się opracować bardziej szczegółowe rozwiązanie.

Powiązane problemy