How to do a fluent nhibernate one to one mapping?

前端 未结 4 857
长情又很酷
长情又很酷 2020-12-02 19:15

How do I do this I am trying to make a one to one mapping.

public class Setting
{
    public virtual Guid StudentId { get; set; }
    public virtual DateFilt         


        
相关标签:
4条回答
  • 2020-12-02 19:36

    There are two basic ways how to map bidirectional one-to-one association in NH. Let's say the classes look like this:

    public class Setting
    {
        public virtual Guid Id { get; set; }
        public virtual Student Student { get; set; }
    }
    
    public class Student
    {
        public virtual Guid Id { get; set; }
        public virtual Setting Setting { get; set; }
    }
    

    Setting class is a master in the association ("aggregate root"). It is quite unusual but it depends on problem domain...

    Primary key association

    public SettingMap()
    {
        Id(x => x.Id).GeneratedBy.Guid();
        HasOne(x => x.Student).Cascade.All();
    }
    
    public StudentMap()
    {
        Id(x => x.Id).GeneratedBy.Foreign("Setting");
        HasOne(x => x.Setting).Constrained();
    }
    

    and a new setting instance should be stored:

            var setting = new Setting();
    
            setting.Student = new Student();
            setting.Student.Name = "student1";
            setting.Student.Setting = setting;
            setting.Name = "setting1";
    
            session.Save(setting);
    

    Foreign key association

    public SettingMap()
    {
        Id(x => x.Id).GeneratedBy.Guid();
        References(x => x.Student).Unique().Cascade.All();
    }
    
    public StudentMap()
    {
        Id(x => x.Id).GeneratedBy.Guid();
        HasOne(x => x.Setting).Cascade.All().PropertyRef("Student");
    }
    

    Primary key association is close to your solution. Primary key association should be used only when you are absolutely sure that the association will be always one-to-one. Note that AllDeleteOrphan cascade is not supported for one-to-one in NH.

    EDIT: For more details see:

    http://fabiomaulo.blogspot.com/2010/03/conform-mapping-one-to-one.html

    http://ayende.com/blog/3960/nhibernate-mapping-one-to-one

    0 讨论(0)
  • 2020-12-02 19:36

    First, define one of the sides of the relationship as Inverse(), otherwise there is a redundant column in the database and this may cause the problem.

    If this doesn't work, output the SQL statements generated by NHibernate (using ShowSql or through log4net) and try to understand why the foreign key constraint is violated (or post it here with the SQL, and don't forget the values of the bind variables that appear afer the SQL statement).

    0 讨论(0)
  • 2020-12-02 19:46

    You should not define the StudentId in Sesstings class. Sessting class already has it (from public virtual Student Student { get; set; } ). Probably it should be SesstingId and you should map the Id field as well (you have to define/map the primary key).

    0 讨论(0)
  • 2020-12-02 19:53

    Here a complete sample with foreign key association

    using System;
    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;
    using NHibernate;
    using FluentNHibernate.Mapping;
    
    namespace NhOneToOne
    {
        public class Program
        {
            static void Main(string[] args)
            {
                try
                {
    
                    var sessionFactory = Fluently.Configure()
                                                 .Database(
                                                        MsSqlConfiguration.MsSql2005
                                                                          .ConnectionString(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=NHTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False")
                                                                          .ShowSql()
                                                  )
                                                 .Mappings(m => m
                                                 .FluentMappings.AddFromAssemblyOf<Program>())
                                                 .BuildSessionFactory();
    
                    ISession session = sessionFactory.OpenSession();
    
    
                    Parent parent = new Parent();
                    parent.Name = "test";
                    Child child = new Child();
                    child.Parent = parent;
                    parent.Child = child;
                    session.Save(parent);
                    session.Save(child);
    
                    int id = parent.Id;
                    session.Clear();
                    parent = session.Get<Parent>(id);
                    child = parent.Child;
    
    
                }
                catch (Exception e)
                {
                    Console.Write(e.Message);
                }
            }
    
        }
    
        public class Child
        {
            public virtual string Name { get; set; }
            public virtual int Id { get; set; }
    
            public virtual Parent Parent { get; set; }
        }
    
        public class Parent
        {
            public virtual string Name { get; set; }
            public virtual int Id { get; set; }
    
            public virtual Child Child { get; set; }
    
        }
    
        public class ChildMap : ClassMap<Child>
        {
            public ChildMap()
            {
                Table("ChildTable");
                Id(x => x.Id).GeneratedBy.Native();
                Map(x => x.Name);
    
                References(x => x.Parent).Column("IdParent");
    
            }
        }
    
        public class ParentMap : ClassMap<Parent>
        {
            public ParentMap()
            {
                Table("ParentTable");
                Id(x => x.Id).GeneratedBy.Native();
                Map(x => x.Name);
    
                HasOne(x => x.Child).PropertyRef(nameof(Child.Parent));
            }
    
        }
    }
    

    And the SQL to create tables

    CREATE TABLE [dbo].[ParentTable] (
        [Id]   INT           IDENTITY (1, 1) NOT NULL,
        [Name] VARCHAR (MAX) NULL
    );
    CREATE TABLE [dbo].[ChildTable] (
        [Id]       INT          IDENTITY (1, 1) NOT NULL,
        [IdParent] INT          NOT NULL,
        [Name]     VARCHAR (50) NULL
    );
    ALTER TABLE [dbo].[ChildTable]
        ADD CONSTRAINT [FK_ChildTable_ToTable] FOREIGN KEY ([IdParent]) REFERENCES [dbo].[ParentTable] ([Id]);
    
    0 讨论(0)
提交回复
热议问题