gpt4 book ai didi

c# - 如何将一对一关系映射为 Fluent NHibernate 中复合键的一部分

转载 作者:行者123 更新时间:2023-11-30 21:59:21 26 4
gpt4 key购买 nike

我有两个表在数据库级别定义父子关系。父表有单列主键,子表有复合主键,其中一列引用父表:

application table       tasks table
= task_id (CK) -------> = taskid (PK)
= user_id (CK)
= transaction_id (CK)

仅供引用,user_idtransaction_id 列不引用其他表。

我正在尝试为 C# 中的两个实体设置 Fluent NHibernate 映射:

public class Application
{
public virtual string UserId { get; set; }
public virtual string TransactionId { get; set; }
public virtual string TaskId { get; set; }

public virtual Task Task { get; set; }
}

public class Task
{
public string Id { get; set; }
}

一个Application有一个Task,但是一个Task有很多Application。我正适应这种关系。

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

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

// No explicit mapping defined for "task_id"
// Other columns mapped, but omitted for brevity
}
}

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

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

// Other columns mapped, but omitted for brevity

// Relations
HasMany(task => task.Applications);
}
}

将新的 Application 插入数据库后,出现以下异常:

NHibernate.QueryException: could not resolve property: TaskId of: Application.

我尝试为 TaskId 属性添加到 ApplicationMap 的显式映射,但我得到了 super 有用的信息“Index was out of range. Must be non-negative and less比集合的大小。”来自 NHibernate 的异常:

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

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

Map(app => app.TaskId, "task_id");

// Other columns mapped, but omitted for brevity
}
}

看完Fluent NHibernate compositeid to mapped class ,我不确定还能尝试什么。这个问题和这个问题的区别在于,子表上的外键列确实需要映射到实体 (Application.TaskId) 中。

我一直在搜索 Fluent NHibernate 文档,但很难找到任何涉及复合主键的内容,尤其是涉及到与其他表的关系时。

为什么需要 TaskIdTask

我确实偶尔需要 Application.Task,但不是很频繁。但是,应用程序表上的组合键用作与应用程序表相关的所有其他表的组合外键引用。 TaskId 属性将被访问很多,我想避免对应用程序和任务表进行 JOIN 查询只是为了获取应用程序中已有的值表。

“失败”的单元测试

我在 NHibernate 中为这个映射和存储库编写了一个单元测试,但它失败了:

var app = new Application(user)
{
TaskId = "...",
// More properties being set...
};

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

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

// Test was failing here
Assert.IsNotNull(actual.Task, "No task found");

真正的问题似乎是新插入记录的 Task 属性为空,并且在从同一个 NHibernate session (这经过一些研究是预期的行为)。

我经历了多次映射迭代,实际上最初的映射确实存在问题。我只是“一直有问题”,因为我不明白 NHibernate 在插入新记录时的行为方式。

最佳答案

我认为您对 TaskClassMap 的映射需要如下所示:

public class TaskClassMap : ClassMap<Task>
{
public TaskClassMap()
{
Table("Task");

Id(task => task.Id, "taskid");
HasMany(c => c.Applications)
.KeyColumn("task_id");
}
}

如果您没有指定特定的列名称 (.KeyColumn),nhibernate 会尝试使用在这种情况下为 TaskId 的约定。

此外,您收到下面臭名昭著的错误的原因还在于您试图在同一映射 (ApplicationMap) 中两次映射同一列 (task_id):

Index was out of range. Must be non-negative and less than the size of the collection.

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

Map(app => app.TaskId, "task_id");

The TaskId property is going to be access a lot, and I'd like to avoid a JOIN query on the application and tasks table just to get a value already in the application table.

还要评论上面的声明,如果您只访问 Application.Task.Id,nhibernate 将不会查询数据库。在执行延迟加载时,nhibernate 会为这种类型的关系创建一个代理对象,其中存储在内存中的唯一字段是主键(Task.Id)。因此,如果您要访问该字段,它实际上不会访问数据库。如果您访问 id 之外的任何其他字段,它将触发对数据库的查询以获取剩余的值。就像你在评论中说的那样,这个值已经存储在 Application 表中,因此 nhibernate 不会查询 Task 表,直到你尝试访问一个值仅在该表中。

关于c# - 如何将一对一关系映射为 Fluent NHibernate 中复合键的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29307899/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com