C# 使用FluentNHibernate的引用上的CustomType

C# 使用FluentNHibernate的引用上的CustomType,c#,nhibernate,fluent-nhibernate,language-ext,C#,Nhibernate,Fluent Nhibernate,Language Ext,我用的是一个叫做。这个库提供了一些工具来处理C#代码中的函数编程。我还使用FluentNHibernate将域类映射到数据库 当属性可为空时,我希望使用LanguageExt中的选项。它是一个结构,要么保存值,要么等于无 我的一个类模型,比如说汽车有一个可选属性,比如说天窗,属于选项类型。像这样: public class Car { Window _sunroof; Option<Window> Sunroof { get => Optional(

我用的是一个叫做。这个库提供了一些工具来处理C#代码中的函数编程。我还使用FluentNHibernate将域类映射到数据库

当属性可为空时,我希望使用LanguageExt中的
选项
。它是一个结构,要么保存值,要么等于无

我的一个类模型,比如说
汽车
有一个可选属性,比如说
天窗
,属于
选项
类型。像这样:

public class Car
{
   Window _sunroof;
   Option<Window> Sunroof
   {
     get => Optional(_sunroof);
     set => _sunroof = value.IfNoneUnsafe(() => null);
   }
}
公车
{
天窗;
选装天窗
{
get=>可选(_);
set=>\u=value.ifnonescape(()=>null);
}
}
我的映射如下所示:

References<Window>(x => x.Sunroof, "idSunroof")
   .Not.Nullable();
参考(x=>x.天窗,“idUnroof”)
.Not.Nullable();
我的问题是:在知道它们不共享相同的返回类型的情况下,如何使用其支持字段映射天窗属性

它是一个域模型,但也通过FluentNHibernate完成的映射配置映射到数据库中的某个表

我认为这不是个好主意。在这一节课上,你要做三件(或者四件)事情,我会把它们分开

我建议为NHibernate提供DTO(可能称为
CarDto
)和商业模式(可能称为
Car
)。这样,
CarDto
可以因与数据库相关的原因(但不是建模原因)而更改,
Car
可以因建模原因(但不是数据库原因)而更改。例如,函数式编程的业务模型是不变的,但NHibernate可能要求其DTO是可变的。如果两种用途使用相同的类型,则无法满足所有设计约束

如果知道天窗属性不共享相同的返回类型,如何使用其支持字段映射天窗属性

我认为您不应该有不同类型的属性和支持字段。使用
CarDto
,使用
null
表示没有
窗口。然后,当从
CarDto
映射到
Car
时,将
null
映射到
None
状态(通过当前使用的
可选
功能)。然后,当从
Car
映射到
CarDto
时,将
None
映射回
null
(通过当前使用的
ifnonescape
方法)

您的
汽车
等级

  • 是NHibernate的DTO
  • 是你的商业模式
  • 包含从DTO到业务模型的映射,以及
  • 包含从业务模型到DTO的映射
  • 这是我上面提到的三件或四件事(取决于是否将映射计算为一件或两件事)

    新增2019-02-20

    [你的答案是]不是我问题的解决方案,而是一个更好架构的建议

    两者都是

    我完全同意你所说的,我很乐意这样做,但我不能。在我的代码库中,我有250多个模型类,它们的设计非常糟糕,并且有很多错误的依赖项。我不能一次重构所有这些

    我不是建议你立刻改变一切。远非如此。以Martin Fowler的风格,我建议随着时间的推移进行许多小的更改

    例如,将
    Car
    更改为

    public class Car
    {
       Option<Window> Sunroof
       {
         get => Optional(SunroofBacking);
         set => SunroofBacking = value.IfNoneUnsafe((Window) null);
       }
       Window SunroofBacking { get; set; }
    }
    
    公车
    {
    选装天窗
    {
    get=>可选(SUNROAFTBACKING);
    set=>sunRootBacking=value.ifNoneSafetable((窗口)null);
    }
    窗口{get;set;}
    }
    

    出于业务逻辑原因,使用(名为“更好”的)属性
    skool
    ,出于
    NHibernate
    原因,使用
    sunrootbacking

    我终于找到了一个解决方案:

    参考(x=>x.天窗,“idUnroof”)
    .Access.CamelCaseField(前缀.下划线)
    .Class();
    
    我不熟悉NHibernate。实体框架具有称为实体的DTO,可以帮助弥合数据库中的数据结构和业务模型中的数据结构之间的差距。NHibernate有这样的车吗?是的,实际上车的级别就是这样。它是一个域模型,但也通过FluentNHibernate完成的映射配置映射到数据库中的某个表。当然,这是获得尽可能纯净的体系结构的方法。不幸的是,在处理遗留代码时,这并不总是现实的。例如,他对此事发表了另一种意见。当然,所有这些都是无休止争论的一个好来源:)你好@XleCustiller。谢谢你的评论。我清楚地知道,许多其他人更喜欢“不那么纯粹”的方法。在我有限的经验中,“更纯粹”的方法总是优越的。给定的代码使用函数式编程库语言Ext。函数式代码通常在软件开发中以及在C#开发中都被认为是“更纯粹的”。我的回答是试图帮助OP解决他们的问题,同时让他们的代码更符合最初使用
    LanguageExt.Option
    的决定。我100%赞同这一点:)我非常感谢你的回答,但我不能接受,因为这不是我问题的解决方案,而是一个更好架构的建议。我完全同意你所说的,我很乐意这样做,但我不能。在我的代码库中,我有250多个模型类,它们的设计非常糟糕,并且有很多错误的依赖项。我不能一次重构所有这些。我更新了我的答案以回应你的评论@Ephasme