流畅的 hibernate 一对一映射

发布于 2024-11-09 02:50:21 字数 3898 浏览 2 评论 0原文

如何进行一对一映射。

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

INSERT 语句与 FOREIGN KEY 约束“FK_Settings_Students”冲突。冲突发生在数据库“Database”、表“dbo.Students”、列“StudentId”中。 该声明已终止。 描述:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息。

异常详细信息:System.Data.SqlClient.SqlException:INSERT 语句与 FOREIGN KEY 约束“FK_Settings_Students”冲突。冲突发生在数据库“Database”、表“dbo.Students”、列“StudentId”中。 该声明已终止。

我缺少什么?

编辑

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

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

studentRepo.SaveSettings(setting);
studentRepo.Commit();

我两种方式都收到这些错误

此 SqlParameterCollection 的索引 5 无效,且 Count=5。描述:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息。

异常详细信息:System.IndexOutOfRangeException:此 SqlParameterCollection 的索引 5 无效,且 Count=5。源错误:第 76 行:使用 (ITransaction transaction = session.BeginTransaction()) 第 77 行:{ 第 78 行:transaction.Commit();第 79 行:} 第 80 行:}

How do I make a 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; }
}

Setting Class map:

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

Student Class map

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

Now every time I try to create a settings object and save it to the database it crashes.

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.

What am I missing?

Edit

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

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

studentRepo.SaveSettings(setting);
studentRepo.Commit();

I get these error for both ways

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

满地尘埃落定 2024-11-16 02:50:21

在 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 -一个

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

⊕婉儿 2024-11-16 02:50:21

这是带有外键关联的完整示例

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

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]);
美人如玉 2024-11-16 02:50:21

首先,将关系的一侧定义为 Inverse(),否则数据库中存在冗余列,这可能会导致问题。

如果这不起作用,请输出 NHibernate 生成的 SQL 语句(使用 ShowSql 或通过 log4net)并尝试理解为什么违反外键约束(或将其与 SQL 一起发布到此处,并且不要忘记绑定 SQL 语句之后出现的变量)。

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).

晌融 2024-11-16 02:50:21

您不应在 Sesstings 类中定义 StudentId。课程已经有它了(来自
公共虚拟学生学生{获取;放; })。也许它应该是 SesstingId 并且您也应该映射 Id 字段(您必须定义/映射主键)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文