导航 属性 不使用 BulkInsert() 保存
Navigation Property Not Saving with BulkInsert()
将 EFCore 3.1 与库 EFCore.BulkExtensions 3.6.1(EFCore 3.1 的最新版本)一起使用。
数据库服务器是 SQL Server 2019。
这是重现错误的代码。
一个简单的客户 class,具有来自另一个 class:
的导航 属性
public class Customer
{
public int ID { get; set; }
public String Name { get; set; }
public Cont Continent { get; set; }
}
public class Cont
{
public int ID { get; set; }
public String Name { get; set; }
}
当我尝试将实体插入具有填充导航属性的客户时
使用 EFCore.BulkExtension 库中的“BulkInsert”方法,导航道具的值不会保存到数据库中:
Customer cust1 = new Customer
{
Continent = contList.Find(x => x.Name == "Europe"),
Name = "Wesson Co, Ltd."
};
Customer cust2 = new Customer
{
Continent = contList.Find(x => x.Name == "Asia"),
Name = "Tiranha, Inc."
};
// (checking the "Continent" props here shows them to be properly populated)
List<Customer> CustomerList = new List<Customer> { cust1, cust2 };
dbContext.BulkInsert(CustomerList);
结果是数据库中的“ContinentID”列为 NULL。
替代方法,与 EF Core SaveChanges() 一样正常工作 - 将最后两行更改为:
dbContext.Customers.AddRange(cust1, cust2);
dbContext.SaveChanges();
这完全没问题。但是我必须插入一百万条记录,而 SaveChanges() 在这种情况下的表现非常糟糕。
我做错了什么吗?
使用另一个(较低)版本的 BulkExtension 没有帮助。更高版本将无法工作,因为它们都以 EFCore 5 和 NetStandard 2.1 为目标,而我的项目目前不支持它。
在 EFCore.BulkExtension 文档中找不到任何提示或提及导航道具相关信息。
寻找 SQL 发送的内容只显示了这样的查询
INSERT INTO dbo.Customers (ContinentID, Name) VALUES @p1, @p2
所以要正确放置值取决于 BulkExtensions.BulkInsert(),但它似乎没有。
重点是类似的代码已经运行了 6 个月,现在对于任何版本的 BulkExtension 库,对于上面的简单场景,它都不会。所以很可能我的代码或我的方法有问题,但找不到它。
更新
将软件包 EFCore.BulkExtensions 降级到 3.1.6 会给我一个不同的错误。仍然不起作用,但这是错误:
System.InvalidOperationException : The given value 'Customer' of type String from the data source cannot be converted to type int for Column 2 [ContinentID] Row 1.
----> System.FormatException : Failed to convert parameter value from a String to a Int32.
----> System.FormatException : Input string was not in a correct format.
就目前而言,这是 EFCore.BulkExtensions 库中的错误 - 版本 3.2.1 到 3.3.5 将(大部分)正确处理它,版本 3.3.6 - 3.6.1 则不能.
在撰写本文时,使用版本 3.3.5 以获得最稳定的结果。
(没有关于 EFCore 5 版本 5.x 的数据)
将 EFCore 3.1 与库 EFCore.BulkExtensions 3.6.1(EFCore 3.1 的最新版本)一起使用。
数据库服务器是 SQL Server 2019。
这是重现错误的代码。
一个简单的客户 class,具有来自另一个 class:
public class Customer
{
public int ID { get; set; }
public String Name { get; set; }
public Cont Continent { get; set; }
}
public class Cont
{
public int ID { get; set; }
public String Name { get; set; }
}
当我尝试将实体插入具有填充导航属性的客户时 使用 EFCore.BulkExtension 库中的“BulkInsert”方法,导航道具的值不会保存到数据库中:
Customer cust1 = new Customer
{
Continent = contList.Find(x => x.Name == "Europe"),
Name = "Wesson Co, Ltd."
};
Customer cust2 = new Customer
{
Continent = contList.Find(x => x.Name == "Asia"),
Name = "Tiranha, Inc."
};
// (checking the "Continent" props here shows them to be properly populated)
List<Customer> CustomerList = new List<Customer> { cust1, cust2 };
dbContext.BulkInsert(CustomerList);
结果是数据库中的“ContinentID”列为 NULL。
替代方法,与 EF Core SaveChanges() 一样正常工作 - 将最后两行更改为:
dbContext.Customers.AddRange(cust1, cust2);
dbContext.SaveChanges();
这完全没问题。但是我必须插入一百万条记录,而 SaveChanges() 在这种情况下的表现非常糟糕。
我做错了什么吗?
使用另一个(较低)版本的 BulkExtension 没有帮助。更高版本将无法工作,因为它们都以 EFCore 5 和 NetStandard 2.1 为目标,而我的项目目前不支持它。
在 EFCore.BulkExtension 文档中找不到任何提示或提及导航道具相关信息。
寻找 SQL 发送的内容只显示了这样的查询
INSERT INTO dbo.Customers (ContinentID, Name) VALUES @p1, @p2
所以要正确放置值取决于 BulkExtensions.BulkInsert(),但它似乎没有。
重点是类似的代码已经运行了 6 个月,现在对于任何版本的 BulkExtension 库,对于上面的简单场景,它都不会。所以很可能我的代码或我的方法有问题,但找不到它。
更新
将软件包 EFCore.BulkExtensions 降级到 3.1.6 会给我一个不同的错误。仍然不起作用,但这是错误:
System.InvalidOperationException : The given value 'Customer' of type String from the data source cannot be converted to type int for Column 2 [ContinentID] Row 1.
----> System.FormatException : Failed to convert parameter value from a String to a Int32.
----> System.FormatException : Input string was not in a correct format.
就目前而言,这是 EFCore.BulkExtensions 库中的错误 - 版本 3.2.1 到 3.3.5 将(大部分)正确处理它,版本 3.3.6 - 3.6.1 则不能.
在撰写本文时,使用版本 3.3.5 以获得最稳定的结果。
(没有关于 EFCore 5 版本 5.x 的数据)