如何在NHibernate中INSERT后启用延迟加载关系

时间:2015-04-01 13:46:35

标签: c# nhibernate orm fluent-nhibernate

我在NHibernate中的两个实体之间有一对多的关系:

public class Application
{
    public string TaskId { get; set; } // Foreign key reference
    public Task Task { get; set; }     // The relation/navigation property
}

db.Web.Applications.Create方法只调用事务中NHibernate会话的“SaveOrUpdate”方法。

相关映射:

internal class ApplicationMap : ClassMap<Application>
{
    public ApplicationMap() : base()
    {
        Schema(...);
        Table(...);

        CompositeId()
            .KeyProperty(app => app.UserId, "...")
            .KeyProperty(app => app.TaskId, "task_id")
            .KeyProperty(app => app.TransactionId, "...");

        // Relations

        References(app => app.Task, "task_id")
            .ForeignKey("taskid")
            .Unique()
            .Not.Insert()
            .Cascade.Persist();
    }
}

internal class TaskMap : ClassMap<Task>
{
    public TaskMap()
    {
        Schema(..);
        Table(...);

        Id(task => task.Id, "task_id");

        HasMany(task => task.Applications)
            .KeyColumn("task_id");
    }
}

当我针对真实数据库编写测试以创建新的Application时,我发现导入属性在插入后没有延迟加载:

var app = new Application(...)
{
    TaskId = "..."
};

db.Web.Applications.Create(app);
db.SaveChanges();

var actual = db.Web.Applications.Find(app.UserId, app.TaskId, app.TransactionId);

// actual.Task is null

映射按预期工作,但在插入新的Application对象后,访问Task属性将返回null,而不是从数据库中延迟加载该实体。可以这样做,如果是这样,怎么办?

1 个答案:

答案 0 :(得分:1)

我认为您的问题来自于您映射Application类的方式以及它对应的Task对象关系。我认为你应该像这样映射它:

public class Application
{
    public Task Task { get; set; }     // The relation/navigation property
}

internal class ApplicationMap : ClassMap<Application>
{
    public ApplicationMap() : base()
    {
        Schema(...);
        Table(...);

        CompositeId()
            .KeyProperty(app => app.UserId, "...")
            .KeyReference(app => app.Task, "task_id")
            .KeyProperty(app => app.TransactionId, "...");
    }
}

internal class TaskMap : ClassMap<Task>
{
    public TaskMap()
    {
        Schema(..);
        Table(...);

        Id(task => task.Id, "task_id");

        HasMany(task => task.Applications)
            .KeyColumn("task_id");
    }
}

无需为外键关系映射特定的id属性。我总是只映射实体。这种方式更容易。然后你上面的代码用于插入:

var app = new Application(...)
{
    Task = session.Load<Task>(taskId)
};

db.Web.Applications.Create(app);
db.SaveChanges();

var actual = db.Web.Applications.Find(app.UserId, app.TaskId, app.TransactionId);