EntityFramework(仅限数据注释)关系未通过 ID 解析
EntityFramework (Data Annotations only) Relationship not resolving with ID
我有两个 classes 的关系。
class ClassA {
[Required]
int Id { get; set; }
[Required]
public int OtherId { get; set; }
[ForeignKey("OtherId")]
public ClassB? Other{ get; set; }
}
class ClassB {
[Required]
int Id { get; set; }
public IEnumerable<ClassA> Others { get; set; } = new List<ClassA>();
}
当我插入 ClassA
的对象时,我是这样做的:
await this.Context.Set<ClassA>().AddAsync(new ClassA() { OtherId = 2 } );
await this.Context.SaveChangesAsync();
这在实时数据库 (Azure SQL DB) 上完美运行。当我像这样添加 class 并稍后从数据库中获取它时(例如,在 SaveChangesAsync
之后),我得到了对象,包括对象 ClassA.Other
.
另一方面,当我 运行 内存数据库上的代码时,它不起作用!插入步骤有效,但不验证 ID (ClassA.OtherId
) 是否存在。这意味着,我可以毫无问题地将 ClassA.OtherId
设置为“12345”,即使我没有 ClassB
的单个条目。如果我插入一个有效的 ClassA.OtherId
它也能正常工作,但是当我从数据库中获取对象时,ClassA.Other
为空。
澄清一下,为什么我写 ClassB? Other
而不是 ClassB Other
。这只是代码的简化版本,我测试得很快,但在我们的生产环境中,出于性能原因,我们 include/exclude 来自某些查询的某些字段。因此,属性 在某些时候可能为空。
大多数 In-memory Testdoubles 在这方面都有一些缺陷,而不是尝试使用 SQlite Provider,因为它的行为更像一个真正的数据库
配置示例:
public static class EfDbContextSqliteBuilderConfigurationFactory
{
internal static Action<DbContextOptionsBuilder> GetSqliteDatabaseOption()
{
const string tempDataBaseFolder = "Database";
EnsureSqliteTempDatabaseFolderExists(tempDataBaseFolder);
return c => c.UseSqlite(new SqliteConnection($"DataSource={tempDataBaseFolder}\{Guid.NewGuid()}.db"));
}
private static void EnsureSqliteTempDatabaseFolderExists(string tempDataBaseFolder)
{
if (!Directory.Exists(tempDataBaseFolder))
{
Directory.CreateDirectory(tempDataBaseFolder);
}
}
}
我有两个 classes 的关系。
class ClassA {
[Required]
int Id { get; set; }
[Required]
public int OtherId { get; set; }
[ForeignKey("OtherId")]
public ClassB? Other{ get; set; }
}
class ClassB {
[Required]
int Id { get; set; }
public IEnumerable<ClassA> Others { get; set; } = new List<ClassA>();
}
当我插入 ClassA
的对象时,我是这样做的:
await this.Context.Set<ClassA>().AddAsync(new ClassA() { OtherId = 2 } );
await this.Context.SaveChangesAsync();
这在实时数据库 (Azure SQL DB) 上完美运行。当我像这样添加 class 并稍后从数据库中获取它时(例如,在 SaveChangesAsync
之后),我得到了对象,包括对象 ClassA.Other
.
另一方面,当我 运行 内存数据库上的代码时,它不起作用!插入步骤有效,但不验证 ID (ClassA.OtherId
) 是否存在。这意味着,我可以毫无问题地将 ClassA.OtherId
设置为“12345”,即使我没有 ClassB
的单个条目。如果我插入一个有效的 ClassA.OtherId
它也能正常工作,但是当我从数据库中获取对象时,ClassA.Other
为空。
澄清一下,为什么我写 ClassB? Other
而不是 ClassB Other
。这只是代码的简化版本,我测试得很快,但在我们的生产环境中,出于性能原因,我们 include/exclude 来自某些查询的某些字段。因此,属性 在某些时候可能为空。
大多数 In-memory Testdoubles 在这方面都有一些缺陷,而不是尝试使用 SQlite Provider,因为它的行为更像一个真正的数据库
配置示例:
public static class EfDbContextSqliteBuilderConfigurationFactory
{
internal static Action<DbContextOptionsBuilder> GetSqliteDatabaseOption()
{
const string tempDataBaseFolder = "Database";
EnsureSqliteTempDatabaseFolderExists(tempDataBaseFolder);
return c => c.UseSqlite(new SqliteConnection($"DataSource={tempDataBaseFolder}\{Guid.NewGuid()}.db"));
}
private static void EnsureSqliteTempDatabaseFolderExists(string tempDataBaseFolder)
{
if (!Directory.Exists(tempDataBaseFolder))
{
Directory.CreateDirectory(tempDataBaseFolder);
}
}
}