LINQ to SQL和外键的基本误解
Posted
技术标签:
【中文标题】LINQ to SQL和外键的基本误解【英文标题】:Basic misunderstanding of LINQ to SQL and foreign keys 【发布时间】:2021-09-23 22:12:30 【问题描述】:我正在处理一个更大的项目,但似乎无法让 LINQ to SQL 以我期望的方式工作。我创建了项目的一个简单子集,因此我可以使用 LinqPad 来确保我对它应该如何工作有一个基本的了解。
显然,我没有:我创建了两个非常简单的表 - customer
和 job
。 customer
表有一个ID
(自动增量)和一个Name
,Job
表有一个ID
(ai)、一个Name
和一个CustomerID
(ID 的外键)在customer
表中)。
当我对最初为空的数据库运行以下代码时:
void Main()
string custName = "James";
string[] jobNames = new string[] "Home Depot", "Menards", "Sam's Club" ;
var cust = customer.FirstOrDefault(c => c.Name == custName);
if (cust == null)
cust = new customer
Name = custName
;
customer.InsertOnSubmit(cust);
foreach(var jn in jobNames)
if (!job.Any(j => j.Customer.Name == cust.Name && j.Name == jn))
job.InsertOnSubmit(new job
Name = jn,
Customer = cust
);
SubmitChanges();
customer.Dump();
job.Dump();
我希望最终在数据库中有 1 个客户和 3 个工作 - 这一切都很好。但是生成的 SQL 和客户 ID 的设置完全不是我所期望的:
SQL --
SELECT t0.ID, t0.Name
FROM customer AS t0
WHERE (t0.Name = @p0)
LIMIT 0, 1
-- p0 = [James]
SELECT COUNT(*) AS value
FROM job AS t0
LEFT OUTER JOIN customer AS t1
ON (t1.ID = t0.CustomerID)
WHERE ((t1.Name = @p0) AND (t0.Name = @p1))
-- p0 = [James]
-- p1 = [Home Depot]
SELECT COUNT(*) AS value
FROM job AS t0
LEFT OUTER JOIN customer AS t1
ON (t1.ID = t0.CustomerID)
WHERE ((t1.Name = @p0) AND (t0.Name = @p1))
-- p0 = [James]
-- p1 = [Menards]
SELECT COUNT(*) AS value
FROM job AS t0
LEFT OUTER JOIN customer AS t1
ON (t1.ID = t0.CustomerID)
WHERE ((t1.Name = @p0) AND (t0.Name = @p1))
-- p0 = [James]
-- p1 = [Sam's Club]
INSERT INTO job(CustomerID, ID, Name)
VALUES (NULL, 0, @p0)
-- p0 = [Home Depot]
INSERT INTO job(CustomerID, ID, Name)
VALUES (NULL, 0, @p0)
-- p0 = [Menards]
INSERT INTO job(CustomerID, ID, Name)
VALUES (NULL, 0, @p0)
-- p0 = [Sam's Club]
INSERT INTO customer(ID, Name)
VALUES (0, @p0)
-- p0 = [James]
SELECT t0.ID, t0.Name
FROM customer AS t0
SELECT t0.CustomerID, t0.ID, t0.Name
FROM job AS t0
LinqPad 中的结果:
我认为 LINQ to SQL 的美妙之处在于我不必设法设置外键,并且我应该能够通过单击数据库来完成我在此处尝试执行的操作。我错过了什么?
编辑:所以我想我理解客户 ID 被设置为 NULL,因为生成的 SQL 在客户的 INSERT 之前对作业调用 INSERT,因此还没有 ID。为什么会这样做?此外,如果我再次运行相同的查询,我会在作业表中再获得三行,但 CustomerID 仍然设置为 NULL。
【问题讨论】:
第 1 步 - 考虑如何编写 SQL(提示 - 将涉及IN
)。
@mjwills 如果我要为这个简单的示例编写 SQL,我不确定我会在哪里使用 IN
,除非您指的是一种简化我的 foreach 循环的方法,即几乎不是问题的重点。
这是使用 LinqPad 自动生成的数据上下文还是您自己的?看起来 Linq2Sql 认为 Customer 表依赖于 Job 表(我怀疑 customer.job 是单个 Job 而不是 EntitySetLinq 查询没有问题。 检查数据库表关系
【讨论】:
我在 SQL Server 中重新创建了我的测试平台(正如您所做的那样),您是对的,代码完全符合我的预期。有谁知道为什么 mysql(实际上是 MariaDB)会有不同的行为? 问题出在参考。请检查外键是如何在数据库中创建的。 (抱歉对mysql没有太多经验)softwaretestinghelp.com/mysql-foreign-key-constraint以上是关于LINQ to SQL和外键的基本误解的主要内容,如果未能解决你的问题,请参考以下文章