2010-02-11 13 views
8

tôi muốn làm chính xác những gì câu hỏi này hỏi: Cascade Saves with Fluent NHibernate AutoMappingLưu lại thác với chế độ tự động chụp liên tục NHibernate - Câu trả lời cũ vẫn hợp lệ?

Sử dụng thành thạo NHibernate Mappings bật "cascade" trên toàn cầu một lần cho tất cả các lớp học và các loại mối quan hệ bằng một cuộc gọi chứ không phải thiết lập nó cho mỗi bản đồ riêng biệt.

Câu trả lời cho câu hỏi trước trông rất tuyệt, nhưng tôi sợ rằng Fluent Nhibernate API đã thay đổi cú pháp .WithConvention vào năm ngoái và đã phá vỡ câu trả lời ... hoặc là tôi đang thiếu thứ gì đó.

tôi tiếp tục nhận được một loạt các không gian tên không tìm thấy sai sót liên quan đến IOneToOnePart, IManyToOnePart và tất cả các biến thể của họ:

"Loại hoặc namespace tên 'IOneToOnePart' không thể tìm được (là bạn thiếu một chỉ thị sử dụng hoặc một tham chiếu lắp ráp?) "

Tôi đã thử dll ví dụ chính thức, dll RTM và bản mới nhất và không ai trong số họ dường như làm VS 2008 xem không gian tên được yêu cầu.

Vấn đề thứ hai là tôi muốn sử dụng lớp với AutoPersistenceModel tôi nhưng tôi không chắc chắn nơi để dòng này: .ConventionDiscovery.AddFromAssemblyOf() trong phương pháp tạo nhà máy của tôi.

private static ISessionFactory CreateSessionFactory() 
      { 

       return Fluently.Configure() 
        .Database(SQLiteConfiguration.Standard.UsingFile(DbFile)) 
        .Mappings(m => m.AutoMappings 
         .Add(AutoMap.AssemblyOf<Shelf>(type => type.Namespace.EndsWith("Entities")) 
           .Override<Shelf>(map => 
           { 
            map.HasManyToMany(x => x.Products).Cascade.All(); 
           }) 
          ) 

        )//emd mappings 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory();//finalizes the whole thing to send back. 

      } 

Dưới đây là những điều khoản về lớp và sử dụng Tôi đang cố gắng

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.IO; 

    using FluentNHibernate.Conventions; 
    using FluentNHibernate.Cfg; 
    using FluentNHibernate.Cfg.Db; 
    using NHibernate; 
    using NHibernate.Cfg; 
    using NHibernate.Tool.hbm2ddl; 
    using FluentNHibernate.Mapping; 


    namespace TestCode 
    { 
     public class CascadeAll : IHasOneConvention, IHasManyConvention, IReferenceConvention 
     { 
      public bool Accept(IOneToOnePart target) 
      { 
       return true; 
      } 

      public void Apply(IOneToOnePart target) 
      { 
       target.Cascade.All(); 
      } 

      public bool Accept(IOneToManyPart target) 
      { 
       return true; 
      } 

      public void Apply(IOneToManyPart target) 
      { 
       target.Cascade.All(); 
      } 

      public bool Accept(IManyToOnePart target) 
      { 
       return true; 
      } 

      public void Apply(IManyToOnePart target) 
      { 
       target.Cascade.All(); 
      } 
     } 

    } 

Trả lời

18

Cách đơn giản nhất tôi đã tìm thấy để làm điều này cho toàn bộ dự án là sử dụng DefaultCascade:

.Conventions.Add(DefaultCascade.All());  

Đi tới mục "The Simplest Conventions" trên wiki, cho điều này và danh sách những người khác.

Edit: Dưới đây là danh sách từ Wiki:

Table.Is(x => x.EntityType.Name + "Table") 
PrimaryKey.Name.Is(x => "ID") 
AutoImport.Never() 
DefaultAccess.Field() 
DefaultCascade.All() 
DefaultLazy.Always() 
DynamicInsert.AlwaysTrue() 
DynamicUpdate.AlwaysTrue() 
OptimisticLock.Is(x => x.Dirty()) 
Cache.Is(x => x.AsReadOnly()) 
ForeignKey.EndsWith("ID") 

Một lời cảnh báo - một số tên phương pháp trong Wiki có thể sai. Tôi đã chỉnh sửa Wiki bằng những gì tôi có thể xác minh (ví dụ: DefaultCascade và DefaultLazy), nhưng không thể xác minh cho phần còn lại. Nhưng bạn sẽ có thể tìm ra những cái tên thích hợp với Intellisense nếu cần.

+0

Cảm ơn tom. Đó là một giải pháp thực sự dễ dàng. Chắc chắn ít mã hơn con đường của tôi :-) – Glenn

+1

Vui vì bạn thích nó - tôi chắc chắn đã làm khi họ đã được chỉ ra cho tôi trên danh sách gửi thư! Tôi đã thực hiện một chỉnh sửa lớn trên phần Wiki http://wiki.fluentnhibernate.org/Conventions để mang lại sự chú ý của nhiều người hơn bằng cách sử dụng FNH. –

1

Chữ ký cho các công ước đã thay đổi. Bạn không sử dụng một cái gì đó như ReSharper? Điều đó sẽ dẫn bạn đến kết luận đó.

Bạn có thể đọc thêm về conventions on the wiki mới.

+0

James, Cảm ơn tất cả công việc tuyệt vời của bạn về Fluent Nhibernate. Tôi là một ngày để thực hiện nó trên một dự án mới và tôi yêu các ví dụ của bạn. Mã (câu trả lời dưới đây) chạy không có lỗi và đặt các giá trị dự kiến ​​trong db. Cách tiếp cận của tôi có ý nghĩa không? – Glenn

2

Dưới đây là một ví dụ làm việc toàn tương tự như hướng dẫn Getting Started https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started

//=====CONSOLE MAIN 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 

    using FluentNHibernate.Cfg; 
    using FluentNHibernate.Cfg.Db; 
    using NHibernate; 
    using NHibernate.Cfg; 
    using NHibernate.Tool.hbm2ddl; 
    using System.IO; 
    using FluentNHibernate.Automapping; 
    using App4.Entities; 
    using System.Diagnostics; 

    namespace App4 
    { 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       // create our NHibernate session factory 
       var sessionFactory = CreateSessionFactory(); 

       using (var session = sessionFactory.OpenSession()) 
       { 
        // populate the database 
        using (var transaction = session.BeginTransaction()) 
        { 
         // create a couple of Stores each with some Products and Employees 
         var topShelf = new Shelf(); 
         var sw = new Stopwatch(); 
         sw.Start(); 
         for (var i = 0; i < 1000; i++) 
         { 
          var potatoes = new Product { Name = "Potatoes" + i.ToString(), Price = 3.60 + i }; 
          var meat = new Product { Name = "Meat" + i.ToString(), Price = 4.49 + i }; 
          //session.SaveOrUpdate(potatoes); //===<<cascading save handles this :-) 
          //session.SaveOrUpdate(meat); 
          topShelf.Products.Add(meat); 
          topShelf.Products.Add(potatoes); 
         } 
         sw.Stop(); 

         session.SaveOrUpdate(topShelf); 
         //session.SaveOrUpdate(superMart); 
         transaction.Commit(); 

         Console.WriteLine("Add Items: " + sw.ElapsedMilliseconds); 
        } 
       } 

       using (var session = sessionFactory.OpenSession()) 
       { 
        // retreive all stores and display them 
        using (session.BeginTransaction()) 
        { 
         var shelves = session.CreateCriteria(typeof(Shelf)).List<Shelf>(); 

         foreach (var store in shelves) 
         { 
          WriteShelfPretty(store); 
         } 
        } 
       } 

       Console.ReadLine(); 
      } 

      private const string DbFile = "FIVEProgram.db"; 
      private static ISessionFactory CreateSessionFactory() 
      { 
       return Fluently.Configure() 
        .Database(SQLiteConfiguration.Standard.UsingFile(DbFile)) 
        .Mappings(m => m.AutoMappings 
         .Add(AutoMap.AssemblyOf<Shelf>(type => type.Namespace.EndsWith("Entities")) 
           .Override<Shelf>(map => 
           { 
            map.HasManyToMany(x => x.Products);//.Cascade.All(); 
           }) 
           .Conventions.AddFromAssemblyOf<CascadeAll>() 
          ) 

        ) //emd mappings 
       .ExposeConfiguration(BuildSchema)//Delete and remake db (see function below) 
       .BuildSessionFactory();//finalizes the whole thing to send back. 

      } 

      private static void BuildSchema(Configuration config) 
      { 
       // delete the existing db on each run 
       if (File.Exists(DbFile)) 
        File.Delete(DbFile); 

       // this NHibernate tool takes a configuration (with mapping info in) 
       // and exports a database schema from it 
       new SchemaExport(config) 
        .Create(false, true); 
      } 

      private static void WriteShelfPretty(Shelf shelf) 
      { 
       Console.WriteLine(shelf.Id); 
       Console.WriteLine(" Products:"); 

       foreach (var product in shelf.Products) 
       { 
        Console.WriteLine(" " + product.Name); 
       } 

       Console.WriteLine(); 
      } 

     } 



    } 


//Data Classes 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace App4.Entities 
{ 
    public class Product 
    { 
     public virtual int Id { get; private set; } 
     public virtual string Name { get; set; } 
     public virtual double Price { get; set; } 
    } 

    public class Shelf 
    { 
     public virtual int Id { get; private set; } 
     public virtual IList<Product> Products { get; private set; } 

     public Shelf() 
     { 
      Products = new List<Product>(); 
     } 
    } 
} 



//Cascade All Helper Class 
using FluentNHibernate.Conventions; 
using FluentNHibernate.Conventions.AcceptanceCriteria; 
using FluentNHibernate.Conventions.Inspections; 
using FluentNHibernate.Conventions.Instances; 
using System; 
using System.Collections.Generic; 


namespace App4 
{ 
    public class CascadeAll : 
     IHasOneConvention, //Actually Apply the convention 
     IHasManyConvention, 
     IReferenceConvention, 
     IHasManyToManyConvention, 

     IHasOneConventionAcceptance, //Test to see if we should use the convention 
     IHasManyConventionAcceptance, //I think we could skip these since it will always be true 
     IReferenceConventionAcceptance, //adding them for reference later 
     IHasManyToManyConventionAcceptance 
    { 

     //One to One 

     public void Accept(IAcceptanceCriteria<IOneToOneInspector> criteria) 
     { 
      //criteria.Expect(x => (true)); 
     } 

     public void Apply(IOneToOneInstance instance) 
     { 
      instance.Cascade.All(); 
     } 




     //One to Many 

     public void Accept(IAcceptanceCriteria<IOneToManyCollectionInspector> criteria) 
     { 
      //criteria.Expect(x => (true)); 
     } 

     public void Apply(IOneToManyCollectionInstance instance) 
     { 
      instance.Cascade.All(); 
     } 




     //Many to One 

     public void Accept(IAcceptanceCriteria<IManyToOneInspector> criteria) 
     { 
      // criteria.Expect(x => (true)); 
     } 

     public void Apply(IManyToOneInstance instance) 
     { 
      instance.Cascade.All(); 
     } 





     //Many to Many 

     public void Accept(IAcceptanceCriteria<IManyToManyCollectionInspector> criteria) 
     { 
      // criteria.Expect(x => (true)); 
     } 

     public void Apply(IManyToManyCollectionInstance instance) 
     { 
      instance.Cascade.All(); 
     } 



    } 


} 
+1

Có vẻ tốt!Giao diện Chấp nhận không cần phải được triển khai nếu bạn không sử dụng tiêu chí, nhưng tôi thu thập bạn biết rằng đã dựa trên nhận xét của bạn. –

+0

Thật tuyệt khi có sự linh hoạt của phương pháp này và sự đơn giản của phương pháp mà Tom đã đề cập bên dưới đối với trường hợp thông thường. Tôi thực sự mong đợi sự bảo trì dễ dàng Fluent sẽ mang lại. Tốc độ cũng rất tuyệt, tôi nhận được hàng ngàn lần chèn mỗi giây bằng cách sử dụng lệnh slq gắn kết đĩa với mã kiểm tra này trong chế độ gỡ lỗi. – Glenn

Các vấn đề liên quan