.net - 使用 EntityFramework Core (3.1.11) 和 SQLite 读取相关实体
问题描述
我在网上发现了类似的问题,但都没有解决我的问题,所以我决定在这里详细描述一下。这是使用 EF Core 创建的简单的一对多关系:
type Parent() =
member val ParentId = Guid() with get, set
member val Name = "" with get, set
member val Relatives = new List<Relative>() with get, set
and Relative() =
member val RemoteKey = Guid() with get, set
member val LocalField = "" with get, set
member val Parent = Parent() with get, set
type TestContext(fileName: string) =
inherit DbContext()
[<DefaultValue>] val mutable parent : DbSet<Parent>
[<DefaultValue>] val mutable relative : DbSet<Relative>
member this.Parent with get() = this.parent and set p = this.parent <- p
member this.Relative with get() = this.relative and set r = this.relative <- r
override this.OnConfiguring(optionsBuilder: DbContextOptionsBuilder) =
optionsBuilder.UseSqlite(dbConnection) |> ignore
override this.OnModelCreating(builder: ModelBuilder) =
builder.Entity<Parent>(fun entity ->
entity.HasKey(fun p -> p.ParentId :> obj) |> ignore
) |> ignore
builder.Entity<Relative>(fun entity ->
entity.HasKey(fun r -> (r.RemoteKey, r.LocalField) :> obj) |> ignore
entity
.HasOne(fun r -> r.Parent)
.WithMany(fun p -> p.Relatives :> seq<_>)
.HasPrincipalKey(fun p -> p.ParentId :> obj)
.HasForeignKey(fun r -> r.RemoteKey :> obj)
|> ignore
) |> ignore
下面的查询返回Relative
在 db 中找到的所有记录。
use db = new TestContext(fileName)
let relatives =
query {
for r in db.Relative.Include(fun r -> r.Parent) do
select r
} |> Seq.toArray
// Assuming 'relatives' is not empty, this prints parent's name
printfn "ParentName: %s" (relatives.[0].Parent.Name)
该查询通过调用显式请求在查询中包含外部记录.Include(fun r -> r.Parent)
。但是,这在另一个方向上不起作用:
use db = new TestContext(fileName)
let parents =
query {
for p in db.Parent.Include(fun p -> p.Relatives) do
select p
} |> Seq.toArray
// Even assuming that 'parents' is not empty and has related entries in the db, this prints an empty array
printfn "Relatives: %A" (parents.[0].Relatives)
问题是:我怎样才能参考Relative
有参考的记录Parent
?
编辑
我注意到使用CLIMutable
Attribute 将类型定义更改为 F# Record 语法可以解决问题。问题是:这两种表示有什么区别。我将使用 ILSpy 并将很快更新。
// This works with .Include(fun p -> p.Relatives)
[<CLIMutable>]
type Parent =
{
ParentId : Guid
Name : string
Relatives : List<Relatives>
}
and [<CLIMutable>] Relative =
{
RemoteKey : Guid
LocalField : string
Parent : Parent
}
编辑 2
我发现这是因为 F# 类默认不允许null
,并且我的实现缺少另一个接受所有参数的构造函数。因此,适用于 EF 的完整定义如下所示:
type [<AllowNullLiteral>] Parent(gid: Guid, field: string, relatives: ICollection<Related>) =
member val Id = gid with get, set
member val Field = field with get, set
member val Relative = relatives with get, set
new() = Parent(Guid.NewGuid(), null, null)
and [<AllowNullLiteral>] Relative(pid: Guid, field: string, parent: Parent) =
member val ParentId = pid with get, set
member val LocalField = field with get, set
member val Parent = parent with get, set
new() = Related(Guid.NewGuid(), null, null)
解决方案
推荐阅读
- java - 多线程 Java 应用程序中的 xpathFactory 问题
- node.js - Express API 响应直接在浏览器中输出,而不是由 Nuxt.js 处理
- javascript - 如何提供不变的唯一键来列出 React 中的项目?
- wifi - 如何关闭 Cox Panoramic Wifi 附带的 safebrowsing.io?
- discord.js - 我如何解除公会的每个成员的禁令
- javascript - 通过php向js发送两个变量
- spring-security - 如何避免在 Spring Security 中为非 TokenRelay 页面应用 Token
- javascript - React.js - 待办事项列表编辑按钮不起作用
- c++ - C ++中按值返回与引用的指南?
- java - 如何在没有docker主机名的情况下在Eureka本地绑定微服务?