簡體   English   中英

如何做一個流利的nhibernate一對一映射?

[英]How to do a fluent nhibernate one to one mapping?

我該怎么做我試圖做一對一的映射。

public class Setting
{
    public virtual Guid StudentId { get; set; }
    public virtual DateFilters TaskFilterOption { get; set; }
    public virtual string TimeZoneId { get; set; }
    public virtual string TimeZoneName { get; set; }
    public virtual DateTime EndOfTerm { get; set; }
    public virtual Student Student { get; set; }

}

//類地圖

 public SettingMap()
        {
           /// Id(Reveal.Member<Setting>("StudentId")).GeneratedBy.Foreign("StudentId");
            //Id(x => x.StudentId);
            Map(x => x.TaskFilterOption).Default(DateFilters.All.ToString()).NvarcharWithMaxSize().Not.Nullable();
            Map(x => x.TimeZoneId).NvarcharWithMaxSize().Not.Nullable();
            Map(x => x.TimeZoneName).NvarcharWithMaxSize().Not.Nullable();
            Map(x => x.EndOfTerm).Default("5/21/2011").Not.Nullable();
            HasOne(x => x.Student);
        }

//學生地圖

public class StudentMap : ClassMap<Student>
    {
        public StudentMap()
        {
            Id(x => x.StudentId);
            HasOne(x => x.Setting).Cascade.All();

        }
    }

  public class Student
    {
        public virtual Guid StudentId { get; private set; }
        public virtual Setting Setting { get; set; }
    }

現在,每當我嘗試創建一個設置對象並將其保存到數據庫時,它就會崩潰。

   Setting setting = new Setting
                                          {
                                              TimeZoneId = viewModel.SelectedTimeZone, 
                                              TimeZoneName = info.DisplayName, 
                                              EndOfTerm =  DateTime.UtcNow.AddDays(-1),
                                              Student = student
                                          };

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Settings_Students". The conflict occurred in database "Database", table "dbo.Students", column 'StudentId'.
The statement has been terminated.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Settings_Students". The conflict occurred in database "Database", table "dbo.Students", column 'StudentId'.
The statement has been terminated.

我錯過了什么?

編輯

public class StudentMap : ClassMap<Student>
{
    public StudentMap()
    {
        Id(x => x.StudentId).GeneratedBy.Guid();
        HasOne(x => x.Setting).PropertyRef("Student").Cascade.All();
    }
}

public class SettingMap : ClassMap<Setting>
{
    public SettingMap()
    {
        Id(x => x.StudentId).GeneratedBy.Guid();
        Map(x => x.TaskFilterOption).Default(DateFilters.All.ToString()).NvarcharWithMaxSize().Not.Nullable();
        Map(x => x.TimeZoneId).NvarcharWithMaxSize().Not.Nullable();
        Map(x => x.TimeZoneName).NvarcharWithMaxSize().Not.Nullable();
        Map(x => x.EndOfTerm).Default("5/21/2011").Not.Nullable();
        References(x => x.Student).Unique();
    }
}

// try 1

      Setting setting = new Setting
                                          {
                                              TimeZoneId = viewModel.SelectedTimeZone, 
                                              TimeZoneName = info.DisplayName, 
                                              EndOfTerm =  DateTime.UtcNow.AddDays(-1),
                                              Student = student
                                          };
     studentRepo.SaveSettings(setting);
     studentRepo.Commit();

// try 2

  Setting setting = new Setting
                                          {
                                              TimeZoneId = viewModel.SelectedTimeZone, 
                                              TimeZoneName = info.DisplayName, 
                                              EndOfTerm =  DateTime.UtcNow.AddDays(-1),
                                              Student = student
                                          };

student.Setting = setting
studentRepo.CreateStudent(student);
studentRepo.Commit();

我兩種方式都有這些錯誤

Invalid index 5 for this SqlParameterCollection with Count=5. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.IndexOutOfRangeException: Invalid index 5 for this SqlParameterCollection with Count=5.

Source Error:

Line 76:             using (ITransaction transaction = session.BeginTransaction()) Line 77:   { Line 78:                 transaction.Commit(); Line 79:         } Line 80:         }

如何在NH中映射雙向一對一關聯有兩種基本方法。 讓我們說這些類看起來像這樣:

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

設置類是關聯中的主(“聚合根”)。 這很不尋常,但這取決於問題領域......

主鍵關聯

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

並應存儲一個新的設置實例:

        var setting = new Setting();

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

        session.Save(setting);

外鍵關聯

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

主鍵關聯與您的解決方案很接近。 只有當您完全確定關聯始終是一對一時,才應使用主鍵關聯。 請注意,NH中的一對一不支持AllDeleteOrphan級聯。

編輯:有關詳細信息,請參閱:

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

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

這里有一個完整的外鍵關聯樣本

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

    }
}

和SQL一起創建表

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]);

首先,將關系的一側定義為Inverse(),否則數據庫中存在冗余列,這可能會導致問題。

如果這不起作用,輸出由NHibernate生成的SQL語句(使用ShowSql或通過log4net)並嘗試理解為什么違反外鍵約束(或在此處使用SQL發布它,並且不要忘記綁定在SQL語句之后出現的變量。

您不應該在Sesstings類中定義StudentId。 Sessting類已經擁有它(來自public virtual Student Student { get; set; } )。 可能它應該是SesstingId,你也應該映射Id字段(你必須定義/映射主鍵)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM