- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
目标框架:.Net Core 2.1
EntityFrameworkCore:2.1.4
我在调用 SaveChanges()
时遇到了一些我不理解的行为。正如标题所说:我有有效的 GUID,这些 GUID 与同一个表具有外键关系,在插入新记录时被替换为 NULL。
不过,这只会发生在特定的列上,并且只会在 EF 为上下文中所做的更改生成 SQL 时发生。我可以在 SSMS 中插入相同的值。
为了演示的目的,我有 created a minimal repository on GitHub您可以使用它来重新创建我遇到的确切问题,但简而言之,如果您有这样的实体:
public class Account
{
[Key]
public Guid AccountId { get; set; }
#region Audit
public Guid? AddedByAccountId { get; set; }
public DateTime AddedOnUtc { get; set; }
public Guid? ModifiedByAccountId { get; set; }
public DateTime ModifiedOnUtc { get; set; }
#endregion Audit
#region Navigation Properties
[ForeignKey(nameof(AddedByAccountId))]
public virtual Account AddedByAccount { get; set; }
[ForeignKey(nameof(ModifiedByAccountId))]
public virtual Account ModifiedByAccount { get; set; }
#endregion Navigation Properties
}
还有一个像这样的派生 DbContext 实现:
public class EntityFrameworkDbContext : DbContext
{
public EntityFrameworkDbContext(DbContextOptions<EntityFrameworkDbContext> options)
: base(options)
{
}
public DbSet<Account> Accounts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>(entity =>
{
// For some reason this self referencing key generates a unique
// constraint in the migration script if we don't set this here.
// "ModifiedByAccountId" does not have this issue! I suspect this might
// the root cause of the NULL data issue.
entity.HasIndex(e => e.AddedByAccountId).IsUnique(false);
});
}
}
在上下文中插入任何内容应该会产生相同的结果。例如:
private void InitialiseDatabase()
{
var systemAccount = new Account
{
AccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
AddedByAccountId = null,
AddedOnUtc = DateTime.UtcNow,
ModifiedByAccountId = null,
ModifiedOnUtc = DateTime.UtcNow
};
var otherAccounts = new List<Account>
{
new Account
{
AccountId = Guid.Parse("015b76fc-2833-45d9-85a7-ab1c389c1c11"),
AddedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
AddedOnUtc = DateTime.UtcNow,
ModifiedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
ModifiedOnUtc = DateTime.UtcNow
},
new Account
{
AccountId = Guid.Parse("538ee0dd-531a-41c6-8414-0769ec5990d8"),
AddedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
AddedOnUtc = DateTime.UtcNow,
ModifiedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
ModifiedOnUtc = DateTime.UtcNow
},
new Account
{
AccountId = Guid.Parse("8288d9ac-fbce-417e-89ef-82266b284b78"),
AddedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
AddedOnUtc = DateTime.UtcNow,
ModifiedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
ModifiedOnUtc = DateTime.UtcNow
},
new Account
{
AccountId = Guid.Parse("4bcfe9f8-e4a5-49f0-b6ee-44871632a903"),
AddedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
AddedOnUtc = DateTime.UtcNow,
ModifiedByAccountId = Guid.Parse("35c38df0-a959-4232-aadd-40db2260f557"),
ModifiedOnUtc = DateTime.UtcNow
}
};
_dbContext.Add(systemAccount);
_dbContext.AddRange(otherAccounts);
try
{
_dbContext.SaveChanges();
}
catch (Exception ex)
{
// Just checking to see if anything was being raised.
}
}
将生成以下 SQL(使用 SQL Server Profiler 捕获并格式化以提高可读性):
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Accounts]
(
[AccountId],
[AddedByAccountId],
[AddedOnUtc],
[ModifiedByAccountId],
[ModifiedOnUtc]
)
VALUES
(
@p5,
@p6,
@p7,
@p8,
@p9
),
(
@p10,
@p11,
@p12,
@p13,
@p14
),
(
@p15,
@p16,
@p17,
@p18,
@p19
),
(
@p20,
@p21,
@p22,
@p23,
@p24
);
',N'@p5 uniqueidentifier,
@p6 uniqueidentifier,
@p7 datetime2(7),
@p8 uniqueidentifier,
@p9 datetime2(7),
@p10 uniqueidentifier,
@p11 uniqueidentifier,
@p12 datetime2(7),
@p13 uniqueidentifier,
@p14 datetime2(7),
@p15 uniqueidentifier,
@p16 uniqueidentifier,
@p17 datetime2(7),
@p18 uniqueidentifier,
@p19 datetime2(7),
@p20 uniqueidentifier,
@p21 uniqueidentifier,
@p22 datetime2(7),
@p23 uniqueidentifier,
@p24 datetime2(7)',
@p5='015B76FC-2833-45D9-85A7-AB1C389C1C11',
@p6=NULL,
@p7='2018-11-10 14:29:25.5363017',
@p8='35C38DF0-A959-4232-AADD-40DB2260F557',
@p9='2018-11-10 14:29:25.5363022',
@p10='538EE0DD-531A-41C6-8414-0769EC5990D8',
@p11=NULL,
@p12='2018-11-10 14:29:25.5363031',
@p13='35C38DF0-A959-4232-AADD-40DB2260F557',
@p14='2018-11-10 14:29:25.5363034',
@p15='8288D9AC-FBCE-417E-89EF-82266B284B78',
@p16=NULL,
@p17='2018-11-10 14:29:25.5363039',
@p18='35C38DF0-A959-4232-AADD-40DB2260F557',
@p19='2018-11-10 14:29:25.5363042',
@p20='4BCFE9F8-E4A5-49F0-B6EE-44871632A903',
@p21='35C38DF0-A959-4232-AADD-40DB2260F557',
@p22='2018-11-10 14:29:25.5363047',
@p23='35C38DF0-A959-4232-AADD-40DB2260F557',
@p24='2018-11-10 14:29:25.5363047'
我怀疑此问题的根源在于我在第二个代码段中突出显示的 "IsUnique(false")
代码行,因为这仅发生在 AddedByAccountId
属性中/柱子。但是,如果我不包含这一行,那么创建的迁移脚本将添加一个唯一约束(我不想要)。
是否有人遇到过在不应该创建约束时创建约束或(更重要的是)NULL 值替换插入时的实际数据的问题?
干杯。
最佳答案
// For some reason this self referencing key generates a unique
// constraint in the migration script if we don't set this here.// "ModifiedByAccountId" does not have this issue! I suspect this might
// the root cause of the NULL data issue.
你猜对了。 EF Core 对 2 个自引用导航属性感到困惑,并错误地决定(可能是错误)它们代表单个 One-to-one。关系:
One to one relationships have a reference navigation property on both sides. They follow the same conventions as one-to-many relationships, but a unique index is introduced on the foreign key property to ensure only one dependent is related to each principal.
当然你想要的是两个一对多的关系,所以不要固定索引(正如你已经看到的那样没有帮助),只需显式映射它们:
modelBuilder.Entity<Account>().HasOne(e => e.AddedByAccount).WithMany();
modelBuilder.Entity<Account>().HasOne(e => e.ModifiedByAccount).WithMany();
关于c# - Entity Framework 核心 : self referencing FK column value being replaced with `NULL` ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53240371/
我不确定这个语法是否是 Informix 特有的,但是我在创建触发器时遇到了麻烦,直到我找到了一些包含这些行之一或两者的语法: CREATE TRIGGER accuplacer_trig
我是 Android Studio 和 gradle 的新手。我有一个 Android 项目,部分在 Eclipse 中工作。原始代码在Android中使用derby数据库。旧代码通过 JDBC 直接
我对以下示例中的行为感到困惑。我在一个项目中偶然发现了这个问题,我花了几个小时将问题缩小到一个简单的例子。所以这是我的简单测试类: 'John']]; public function inf
我在 pgAdmin 4 中创建了一些表,但由于某种原因我一直收到标题错误,你能找出原因吗?我没有看到任何问题,并且我已经查看了与我的代码示例相似的其他代码示例,这些示例编译得很好。它在 IDEone
我正在创建一个表,但出现此错误: number of referencing and referenced columns for foreign key disagree. 不知道怎么解决。我认为声
假设我有一个名为“C”的库 (.NETStandard 2.0),它定义了一个名为“CRecord”(记录)的类型。 假设我从名为“B”的 .NET 4.7.2 库中使用这个库。有一个使用“CReco
我已经尝试解决这个错误几分钟了,但我不知道表定义中缺少什么。 表格的代码如下: 表Autocare: CREATE TABLE [dbo].[Autocare] ( [IDAutocar]
DROP DATABASE IF EXISTS ProviderPatients; CREATE DATABASE ProviderPatients; USE ProviderPatients; CR
假设我有这个表stuff_property: | stuff_id (fk) | property_id | | ------------- | ----------- | 现在我想要进行查询,该查询
我是 MySQL 的新手。我完全有能力进行查询和创建表,但之前从未尝试过触发器。 CREATE TRIGGER TrigMora AFTER INSERT ON cliente REFEREN
我可以创建一个具有四个这样的属性的对象 $pocketKnife = New-Object PSObject -property @{ Color = 'Black' Weight =
我有一个名为 App 的对象,它包含主干应用程序的所有相关部分。 问题:当我从应用程序中的其他对象调用应用程序中的对象时,它们是未定义的。 我认为发生这种情况是因为在定义其自身的 App 对象之前,它
我有一个ArrayClass并且mergeSortArray扩展了它。并且 mergeSortArray 包含一个 mergeSort() 方法。但是,由于我使用 super 从父类(super cl
public class foo{ private String label; foo(String whereto){ label = whereto; } publi
我正在尝试以编程方式将库添加到引用的库中。这是我的代码: String filename = "myfile.jar"; InputStream is; try { is = new Buffe
我使用@Reference来获取我需要的所有信息: 吗菲亚: Query query = INSTANCE.createQuery(User.class); return query.asLi
我在 eclipse 中有一个 Java 项目,我想在其中添加 3 个 jar 文件到构建路径: 但是,当我选择它们并将它们添加到构建路径(右键单击/构建路径/添加到构建路径)时,它们将与成为类的“j
希望获得 Java 遵循的一些幕后内存引用和规则。 这是一段代码。基本上,此类用于实例化一些其他对象 (MyOtherObject),然后将此对象的 doClose() 方法的引用发送到 Vector
我打开了this关于转发引用的帖子,这是一个(希望如此)MCVE 代码: #include #include using namespace std; struct MultiMemoizator
MySQL 表: categoryID categoryName categoryParent 每个类别都有一个父类别,尽管它可以是 NULL,我将其视为根类别。 我想从表中获取所有类别,将其存储
我是一名优秀的程序员,十分优秀!