使用流畅的NHibernate AutoMapping保存级联 - 旧答案仍然有效吗?

时间:2010-02-11 07:34:27

标签: c# fluent-nhibernate

我想做的问题是: Cascade Saves with Fluent NHibernate AutoMapping

使用Fluent Nhibernate映射使用一次调用为所有类和关系类型全局打开“级联”,而不是单独为每个映射设置它。

早期问题的答案看起来很棒,但我担心Fluent Nhibernate API去年改变了它的.WithConvention语法并且打破了答案......或者我错过了什么。

我不断收到一堆未找到与IOneToOnePart,IManyToOnePart及其所有版本相关的名称空间错误:

“找不到类型或命名空间名称'IOneToOnePart'(您是否缺少using指令或程序集引用?)”

我已经尝试了官方示例dll,RTM dll和最新版本,但似乎没有一个让VS 2008看到所需的命名空间。

第二个问题是我想将该类与我的AutoPersistenceModel一起使用 但我不确定这条线在哪里:    .ConventionDiscovery.AddFromAssemblyOf()  在我的工厂创建方法。

 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. 

            }

以下是我正在尝试的类和使用语句

   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();
            }
        }

    }

3 个答案:

答案 0 :(得分:18)

我发现在整个项目中执行此操作的最简单方法是使用 DefaultCascade

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

转到维基上的"The Simplest Conventions"部分,以及其他人的列表。

修改 以下是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")

警告 - Wiki中的某些方法名称可能有误。我用我可以验证的内容(即DefaultCascade和DefaultLazy)编辑了Wiki,但不能保证其余的。但是如果需要,你应该能够用Intellisense找出正确的名称。

答案 1 :(得分:2)

以下是与“入门指南”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();
        }



    }


}

答案 2 :(得分:1)

约定的签名已更改。你没有使用像ReSharper这样的东西吗?这将指出你的结论。

您可以阅读有关新conventions on the wiki

的更多信息