假设我有以下类用于从数据库映射对象:
public class OwnedThingie
{
public long Id {get;set;}
public long OwnerId {get;set;}
public UserMan Owner {get;set;}
}
public class UserMan
{
public long Id {get;set;}
public string Name {get;set;}
public List<OwnedThingie> Thingies {get;set;}
}
我使用以下流畅的映射:
For<OwnedThingie>()
.TableName("DbThingies")
.PrimaryKey(o => o.Id, true)
.Columns
(
c =>
{
c.Column(o => o.Id);
c.Column(o => o.OwnerId);
c.Column(o => o.Owner).WithName("OwnerId").Reference( um => um.Id, ReferenceType.OneToOne )
},
true
);
For<UserMan>()
.TableName("DbUsers")
.PrimaryKey(u => u.Id, true)
.Columns
(
c =>
{
c.Column(u => u.Id);
c.Column(u => u.Name);
c.Many(u => u.Thingies).Reference(o => o.OwnerId)
},
true
);
这将造成巨大的内存泄漏,因为它不会将所有者 <-> thingies 识别为循环关系(具体来说,它会将OneToOne
关系从 Thingie 映射到 User,然后找到与 Thingie 的Many
关系,再次映射 Thingie,找到用户等等......)
我们确实需要在数据模型上同时拥有列OwnerId
和属性。Owner
使用过去的参考是OneToOne
要走的路,但不幸的是,如果你想建立适当的关系,它会像上面所说的那样吃掉你所有的记忆。
提供一个参考框架,当我说“你所有的内存”时,我的意思是具有 17 个简单表的映射配置将导致 NPOCO 支持的服务吞下 1 到 3GB 的内存。
什么已经尝试过:
- 通过手动保持计数或参考链,有条件地阻止它在地图中包含太多嵌套层。至少到目前为止失败了,因为似乎没有办法正确检查更大的上下文。
- 使用
.Result()
and.Computed()
来克服对 same-field-name 的限制(OwnerId
如果您的Foreign
引用被命名,则不能有字段OwnerId
)。失败,因为名称保存在字典中,你无法绕过它。 - 创建包含通用对象而不是实际数据对象的不同模型以停止连接传播。需要明确的是,
class SuperUserMan: UserMan
简单的 s 隐藏了令人讨厌的关系object
。失败的原因尚不清楚,但很可能被 NPOCO 视为动态的。内存使用率更高。 - 只是假装 FK 属性仍然存在 - 尝试在我们的代码中使用它们,或者更确切地说是 NPOCO 的 LINQ 表达式。失败,因为它们已添加到字典中但不能以任何方式使用。
任何建议都非常受欢迎。
使用 NPOCO 最新版本、SQL Server 2019、.NET Core 目前为 3.1.latest
这也已在 NPOCO GitHub 中作为问题打开 - 但是在这里我问是否有人有不涉及以任何方式接触 NPOCO 的解决方案。