C# 如何进行流畅的nhibernate一对一映射?
我是如何做到这一点的我正在尝试做一对一的映射C# 如何进行流畅的nhibernate一对一映射?,c#,nhibernate,fluent-nhibernate,C#,Nhibernate,Fluent Nhibernate,我是如何做到这一点的我正在尝试做一对一的映射 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 { ge
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).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();
首先,将关系的一侧定义为Inverse(),否则数据库中会有一个冗余列,这可能会导致问题
如果这不起作用,请输出NHibernate生成的SQL语句(使用ShowSql或通过log4net),并尝试了解违反外键约束的原因(或将其与SQL一起发布在此处,并且不要忘记SQL语句后面出现的绑定变量的值).您不应该在Sesstings类中定义StudentId。Sessting类已经有了它(从
公共虚拟学生学生{get;set;}
)。可能应该是SesstingId,您也应该映射Id字段(您必须定义/映射主键)。在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; }
}
Setting类是关联中的主节点(“聚合根节点”)。这是很不寻常的,但它取决于问题领域
主键关联
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();
}
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");
}
并应存储一个新的设置实例:
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();
HasOne(x => x.Student).Cascade.All();
}
public StudentMap()
{
Id(x => x.Id).GeneratedBy.Foreign("Setting");
HasOne(x => x.Setting).Constrained();
}
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级联
编辑:有关详细信息,请参阅:
这里是一个完整的外键关联示例
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));
}
}
}
如果我从设置中删除StudentId,那么nhibernate将崩溃,至于PKHmm,这很奇怪。我从未见过这样的例外。它有内部异常吗?是否使用侦听器或拦截器?问题可能是在设置类中有两个属性映射到一列:Student reference和StudentId property。请参阅:。我刚刚创建了一个示例项目,其中“表A”有一个主键,“表B”有一个主键,该主键也是“表A”的外键。在这种情况下,外键关联非常有效。需要记住的重要一点是,“表B”映射需要分别映射主键值和HasOne关联?
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));
}
}
}
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]);