通过代码映射-双向关系
本文关键字:关系 -双 映射 代码 | 更新日期: 2023-09-27 18:30:02
我有一个Parent-Children关系,目前,只有每个子级对父级的引用存在(子表上有一个外键列)。我想向父级添加一个只读IEnumerable属性,但我没能做到。
public class ProjectData : Entity
{
public virtual long Id {get;set;}
private readonly IList<BranchData> _branches = new List<BranchData>();
public virtual IEnumerable<BranchData> Branches
{
get { return _branches.AsReadOnly(); }
}
}
public class BranchData : Entity
{
puplic virtual long Id {get;set;}
public virtual ProjectData ProjectData { get; set; }
}
public class BranchDataMapping : ClassMapping<BranchData>
{
public BranchDataMapping()
{
ManyToOne(x => x.ProjectData, mapper => { });
}
}
public class ProjectDataMapping : ClassMapping<ProjectData>
{
public ProjectDataMapping()
{
Bag(data => data.Branches,
mapper =>
{
mapper.Access(Accessor.ReadOnly);
mapper.Inverse(false);
}, relation => relation.OneToMany());
}
}
表名和列名是按照约定创建的。当创建并保存设置了父属性的新BranchDate时,它不会出现在父属性的Branches集合中。
我错过了什么场景?
我已经阅读了双向NHibernate映射的代码和http://notherdev.blogspot.cz/2012/02/nhibernates-mapping-by-code-summary.html但我还是没能把它设置好。
编辑:验证此行为的代码
[Test]
public void CanSaveAndLoadBranch()
{
var session = InMemoryDatabase.GetSession();
var project = new ProjectData {Name = "ratata"};
var branch = new BranchData {ProjectData = project};
using (var tx = session.BeginTransaction())
{
session.Save(project);
session.Save(branch);
tx.Commit();
}
var branches = project.Branches;
//branches are empty
var freshProject = session.Query<ProjectData>().Where(x => x.Id == project.Id).First();
var freshBranches = freshProject.Branches;
//branches are empty here, too
var fetched = session.Query<ProjectData>().Where(x => x.Id == project.Id).FetchMany(x => x.Branches).First();
var fetchedBranches = fetched.Branches;
//branches are empty here, too
var queriedOn = session.Query<ProjectData>().Where(x => x.Branches.Any()).ToList();
//this does return the project, but Branches property is still empty
}
在处理内存中的数据时,您负责管理关系的双方。使用ProjectData
:中的Add
方法可以轻松完成此操作
public virtual void Add(BranchData branch)
{
branch.ProjectData = this;
Branches.Add(branch);
}
另一方面,NHibernate负责对你的物品进行适当的补水和脱水。但是,您没有看到这一点,因为您的查询都发生在同一会话中。考虑这个代码:
var project = new ProjectData();
session.Save(project);
session.Flush();
var freshProject = session.Get<ProjectData>(project.Id);
if (ReferenceEquals(project, freshProject))
Console.WriteLine("They're the same instance.");
这段代码将显示"它们是同一个实例。"该实例仍然会按照您初始化它们的方式设置关系,无论是否正确。
如果您忽略了在相反一侧设置关系project.Branches
,NHibernate仍然可以很好地保存它,但在该会话期间,它仍然看起来不一致。如果您关闭会话并打开一个新会话(这可能会对内存测试产生问题),或者只调用session.Clear()
或session.Evict(project)
,那么当您再次加载它时,您将在project.Branches
中看到数据。