Entity Framework 核心:将转换应用到 F# 中 Option<T> 类型的所有属性
Entity Framework Core : Apply Conversion to all properties of type Option<T> in F#
我在 F# 中使用 Entity Framework Core 2.1。
我想为 Option
类型设置泛型类型转换,以便 EF 知道如何处理它们。
我发现 this 非常有用 post,它展示了如何为 Option
类型设置通用转换器。
所以这就是我到目前为止所拥有的(将片段放在一起)
[<Table("Users", Schema = "pm")>]
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : DateTimeOffset option
}
with
static member Configure (mb : ModelBuilder) =
mb.Entity<User>()
.Property(fun p -> p.LastLoggedInTime)
.HasConversion(OptionConverter<DateTimeOffset>()) |> ignore
这很好,除非我在我的类型中添加一个新的 属性。我还需要为 属性 添加上述代码的最后三行。我正在寻找一种方法来一次性处理所有属性 :D
然后我发现 有用的 SO 答案让我找到了下面的代码
let tt = mb.Model.GetEntityTypes()
|> Seq.map(fun et -> et.GetProperties()) |> Seq.concat
|> Seq.filter(fun p -> p.ClrType = typeof<Option<DateTimeOffset>>)
|> Seq.map(fun p -> mb.Entity(p.DeclaringEntityType.ClrType)
.Property(p.Name)
.HasConversion(OptionConverter<DateTimeOffset>()))
现在我要解决的问题是弄清楚如何使此代码与通用类型一起工作,这样我就不必指定类型。我希望它像 p.ClrType = typeof<Option<T'>>
那样,最后像 .HasConversion(OptionConverter<T'>())
有什么想法吗?
所以离开你最初的问题 "I want to setup a generic type conversion for Option types so that EF knows how to handle them." 我假设你的意思是你希望 EF 正确地将一个选项映射到相应基本类型的 "NULL" 列,并且你遇到问题是因为EF 不知道如何处理 FSharp.Option?
您可以只使用 Nullable 代替 EF 类型的 Option,它将像在 C# 中一样解析。
例如,您的示例类型变为:
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : Nullable<DateTimeOffset>
}
对于不能为 Nullable 但在您的域中是 Options 的类型(例如字符串),您只需将它们设置为它们的基本类型,它就可以正常工作。
如果您要映射到其他地方的 F# 域类型,您可以只在那里使用 Option.ToNullable 和 Option.OfNullable,或者如果类型不能为 null,则将 None 映射到 null多于。
希望对您有所帮助!
我在 F# 中使用 Entity Framework Core 2.1。
我想为 Option
类型设置泛型类型转换,以便 EF 知道如何处理它们。
我发现 this 非常有用 post,它展示了如何为 Option
类型设置通用转换器。
所以这就是我到目前为止所拥有的(将片段放在一起)
[<Table("Users", Schema = "pm")>]
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : DateTimeOffset option
}
with
static member Configure (mb : ModelBuilder) =
mb.Entity<User>()
.Property(fun p -> p.LastLoggedInTime)
.HasConversion(OptionConverter<DateTimeOffset>()) |> ignore
这很好,除非我在我的类型中添加一个新的 属性。我还需要为 属性 添加上述代码的最后三行。我正在寻找一种方法来一次性处理所有属性 :D
然后我发现
let tt = mb.Model.GetEntityTypes()
|> Seq.map(fun et -> et.GetProperties()) |> Seq.concat
|> Seq.filter(fun p -> p.ClrType = typeof<Option<DateTimeOffset>>)
|> Seq.map(fun p -> mb.Entity(p.DeclaringEntityType.ClrType)
.Property(p.Name)
.HasConversion(OptionConverter<DateTimeOffset>()))
现在我要解决的问题是弄清楚如何使此代码与通用类型一起工作,这样我就不必指定类型。我希望它像 p.ClrType = typeof<Option<T'>>
那样,最后像 .HasConversion(OptionConverter<T'>())
有什么想法吗?
所以离开你最初的问题 "I want to setup a generic type conversion for Option types so that EF knows how to handle them." 我假设你的意思是你希望 EF 正确地将一个选项映射到相应基本类型的 "NULL" 列,并且你遇到问题是因为EF 不知道如何处理 FSharp.Option?
您可以只使用 Nullable 代替 EF 类型的 Option,它将像在 C# 中一样解析。
例如,您的示例类型变为:
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : Nullable<DateTimeOffset>
}
对于不能为 Nullable 但在您的域中是 Options 的类型(例如字符串),您只需将它们设置为它们的基本类型,它就可以正常工作。
如果您要映射到其他地方的 F# 域类型,您可以只在那里使用 Option.ToNullable 和 Option.OfNullable,或者如果类型不能为 null,则将 None 映射到 null多于。
希望对您有所帮助!