6

olarak yabancı bir anahtar haritalama. Önceki yazılar yoluyla aradık ama bulabilirim yakın ilişki .Load için bir öneridir - Ben umuyorum değil ne. Bu .HasForeignKey bağlayıcı ile Entity Framework yapılabilir biliyorum ama Akıcı NHibernate bunu yapmak için bir yol bulmak gibi olamaz.Akıcı NHibernate - Ben iki varlık arasında bir ilişki ekleme ve yabancı anahtar için bir ayarlanabilir Kimlik'i bir yol arıyorum bir özellik

iki örnek varlıkları atın:

public class Ticket 
{ 
    public virtual int Id { get; set; } 
    public virtual string Title { get; set; } 
    public virtual string ServiceId { get; set; } 
    public virtual Service Service { get; set; } 
} 

public class Service 
{ 
    public virtual string Id { get; set; } 
} 

Ben Biletin yeni bir örneğini oluşturmak için mümkün istiyorum ve aşağıdaki araçları kullanarak buna bir Hizmetleri atamak (farz olduğunu ilişkili Servis zaten) tablosunda var:

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    ServiceId = "Microsoft Word 2012" 
}; 

ne yapmak istemiyorum şudur:

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    Service = Session.Load<Service>("Microsoft Word 2012") 
}; 

Bunun için geçerli nedenleri var, ve benzeri bu Entity Framework yapılabilir, ama gerçekten Akıcı NHibernate aynı şeyi başarmak için nasıl olarak stumped söyledim. Eşlemlerim şu anda şöyle görünür:

public class TicketMapping : ClassMap<Ticket> 
{ 
    public TicketMapping() 
    { 
     Id(m => m.Id); 
     Map(m => m.Title).Column("Title"); 
     Map(m => m.ServiceId).Column("ServiceId"); 
     HasOne(m => m.Service).ForeignKey("ServiceId"); 

     Schema("dbo"); 
     Table("Tickets"); 
    } 
} 

public class ServiceMapping : ClassMap<Service> 
{ 
    public ServiceMapping() 
    { 
     Id(m => m.Id); 

     Schema("dbo"); 
     Table("Services"); 
    } 
} 

Herhangi bir yardım her zaman minnettar! Jay için


Sadece hızlı düzenleme - Ben elemanı Session.Load istemiyorum sebebi benim sunum katmanı (MVC 3) NHibernate hakkında bilmeden şey istemiyoruz çünkü - bu nedenle Bir havuz kalıbı kullanarak ve kontrolöre tek bir depo enjekte ederek. Yani, örneğin, ben de sadece Hizmet bir başvuru için almak için bir ServiceRepository enjekte etmek zorunda istemiyorum

public interface IRepository<T> 
{ 
    T GetById(object id); 
    void Create(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
} 

aşağıdaki sözleşme yapışan bir TicketRepository olacak Bilet.

+1

'Session.Load' kullanmak istemediğinden geçerli nedenleri açıklayabilir misiniz? – Jay

+1

@Jay, Terric'in nedenlerinden emin değilsiniz ... ama kaydetmeden önce, IMHO'ya zaten sahip olduğunuz anahtarı referans alabilmek için bir nesneyi yüklemek bazen çok saçma olabilir. Bir önceki projede sıkı bir SLA vardı ve burada da aynı desteği FK desteği almadan önce Entity Framework üzerinde yapmak zorunda kaldık. –

+0

@Jay, yazıyı nedenlerle güncelledi. Ayrıca, Kevin iyi bir noktaya işaret ediyor, ben bunun için bir başka varlık yükleme ekstra yükünü istemiyorum. –

cevap

3

Ben gerçekten NHibernate kullanırken Session.Load (id) kullanarak kaçınamaz gördüğü gibi. Yorumlarda belirtildiği gibi bu veritabanına vurmaz, sadece kimliğine sahip bir proxy nesnesi yaratır.

bazı olası seçenekleri:

  1. denetleyici içine ikinci bir jenerik depo (ServiceRepository) enjekte edin. Bununla bir sorunu gerçekten göremiyorum, ama bir sebepten dolayı bunu önlemek istiyorsun. Sen jenerik arabirimine bir LoadById yöntemi ekleyip NH ve EF (ve başkaları) için her bir uygulamada farklı olduğunu uygulayabilir. EF'de, bu yöntem GetById gibi çalışabilirken, NH uygulamasında Session.Load
  2. olarak adlandırılır. AR (toplanmış kök) için bu durumda Bilet olmayan genel bir depo uygulayın. Bu, bir Hizmetin yanı sıra Bilet Yükleme için belirli yöntemlere sahip olabilir.
  3. İki deponun üstünde başka bir soyutlama gerçekleştirin ve seçenek 1'deki iki deponun yerine denetleyiciye bunu enjekte edin. Bu, f.Burada ana hatlarıyla belirtildiği gibi bir cehalet UnitOfWork: Persistance ignorant UoW veya Bilet Oluşturma'yı düzenleyen bir çeşit Uygulama Hizmeti veya bir TicketFactory.

3 seçenek arasından, seçenek 1 muhtemelen en basittir, 3 ise daha iyi bir soyutlama ve yolda daha fazla bakım sağlayabilir.

+0

Teşekkürler, 'Session.Load' hakkında daha iyi bir anlayışa sahip olmak artık onu kullanmaktan endişelenmemek anlamına geliyordu. Bunun yerine varlık çerçevesini kullanarak bitirdim ve NHibernate'i düşürdüm (esasen EF ile daha rahat olduğum için ama NH'nin ne sunduğunu görmek istediğim için). –

+0

Yabancı anahtarlarımı nesneler yerine ints içine çevirme fikrini atıyordum çünkü bu soruya rastladım ve bu konuya gelene kadar her ekleme veya güncellemede her bağlantılı nesne için DB'ye vurmak istemedim. Session.Load(). Basit operasyonlar için nhibernate log sonuçlarını karşılaştırdıktan sonra - vay! BÜYÜK tasarruf! Teşekkürler! – Brett

0

Bir numara kullanabilirsiniz. Kodunuzu temiz tutmak için.

Bu bir NH meselesidir ki, NH Havuzlarında çözüm uygulamak zorundasınız, ben de bunu çözüyorum.

önce ekleyin veya

if (!string.IsNullOrEmpty(ServiceId) && Service == null) 
{ 
    Service = new Service{ Id = ServiceId }; 
} 

Normal depo işi güncelleyin ...

bunu test etmek ve çalışma. Mimariniz hala ORM kararlarını temizliyor

+0

, Hizmet sınıfı birden çok alana sahipse, bu durumda tüm alanları buraya atamamız gerektiğini varsayalım? aynı problemle karşı karşıya olduğumda .. – jkyadav

İlgili konular