C# 使用LINQ删除记录时出错
我尝试将SQL Delete命令更改为LINQ。这是我的SQL命令:C# 使用LINQ删除记录时出错,c#,.net,linq,linq-to-sql,exception-handling,C#,.net,Linq,Linq To Sql,Exception Handling,我尝试将SQL Delete命令更改为LINQ。这是我的SQL命令: DELETE FROM [TrackPoints] WHERE [RouteFK] IN (SELECT RouteId FROM Routes WHERE UserId = @UserId) 这是我写的LINQ代码: int UID =1; FirstDataContext aspnetdb = new FirstDataContext();
DELETE FROM [TrackPoints]
WHERE [RouteFK] IN (SELECT RouteId
FROM Routes
WHERE UserId = @UserId)
这是我写的LINQ代码:
int UID =1;
FirstDataContext aspnetdb = new FirstDataContext();
var res1 = from q1 in aspnetdb.Routes
where q1.UserId == UID
select q1.RouteId;
foreach (var k in res1)
{
var eigen = from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p.TrackPointId;
aspnetdb.Trackpoints.DeleteOnSubmit(eigen.First());
aspnetdb.SubmitChanges();
}
但在这一行我有一个错误:
aspnetdb.Trackpoints.DeleteOnSubmit(eigen.First());
也就是说:
与“System.Data.Linq.Table.DeleteOnSubmit(Linq_Test.Trackpoint)”匹配的最佳重载方法具有一些无效参数
我该怎么办 使用以下命令:
var eigen = (from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p).First();
或者更短的是:
var eigen = aspnetdb.Trackpoints.First(p => p.RouteFK == k);
因为它返回Trackpoint
而您的选择p.TrackPointId
将返回Int
使用以下命令:
var eigen = (from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p).First();
或者更短的是:
var eigen = aspnetdb.Trackpoints.First(p => p.RouteFK == k);
因为它返回Trackpoint
而您的选择p.TrackPointId
将返回Int
问题是您只是选择了ID,而ID与方法签名不匹配。实际上,我会将您的代码更改为:
var entity = aspnetdb.Trackpoints.Where(p => p.RouteFK == k).Single();
aspnetdb.Trackpoints.DeleteOnSubmit(entity);
(当您将select
子句更改为justselect p
时,使用查询表达式就变得毫无意义了——一旦您使用了方法调用语法,在同一语句中调用Single
或First
是有意义的。根据abatishchev的回答,这也可能是aspnetdb.Trackpoints.Single(p=>p.RouteFK==k)
)
顺便说一句,这假设对于给定的RouteFK您肯定有1个(并且只有1个)实体
实际上,最好在一个查询中选择要删除的所有实体。例如:
var entitiesToDelete = from q1 in aspnetdb.Routes
where q1.UserId == UID
join p in aspnetdb.TrackPoints
on q1.RouteID equals p.RouteFK
select p;
aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete);
aspnetdb.SubmitChanges();
或者,如果已在模型中正确设置联接,则可能可以取消显式联接:
var entitiesToDelete = from q1 in aspnetdb.Routes
where q1.UserId == UID
select q1.Route; // Or Track, or whatever it is
aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete);
aspnetdb.SubmitChanges();
在这两种情况下,您都可以避免执行几乎同样多的查询。(您可以避免“n+1选择”问题。)问题在于您只是选择了ID,而ID与方法签名不匹配。我实际上会将您的代码更改为:
var entity = aspnetdb.Trackpoints.Where(p => p.RouteFK == k).Single();
aspnetdb.Trackpoints.DeleteOnSubmit(entity);
(当您将select
子句更改为justselect p
时,使用查询表达式就变得毫无意义了——一旦您使用了方法调用语法,在同一语句中调用Single
或First
是有意义的。根据abatishchev的回答,这也可能是aspnetdb.Trackpoints.Single(p=>p.RouteFK==k)
)
顺便说一句,这假设对于给定的RouteFK您肯定有1个(并且只有1个)实体
实际上,最好在一个查询中选择要删除的所有实体。例如:
var entitiesToDelete = from q1 in aspnetdb.Routes
where q1.UserId == UID
join p in aspnetdb.TrackPoints
on q1.RouteID equals p.RouteFK
select p;
aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete);
aspnetdb.SubmitChanges();
或者,如果已在模型中正确设置联接,则可能可以取消显式联接:
var entitiesToDelete = from q1 in aspnetdb.Routes
where q1.UserId == UID
select q1.Route; // Or Track, or whatever it is
aspnetdb.Trackpoints.DeleteAllOnSubmit(entitiesToDelete);
aspnetdb.SubmitChanges();
在这两种情况下,您都可以避免执行几乎相同数量的查询。(您可以避免“n+1选择”问题。)方法需要域对象。您的代码将传递一个
ID
。此外,您还缺少检查该项是否实际存在的条件
尝试将您的例程改写为以下内容:
foreach (var k in res1)
{
var eigen = from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p;
var item = eigen.FirstOrDefault();
if ( item != null )
{
aspnetdb.Trackpoints.DeleteOnSubmit(item);
aspnetdb.SubmitChanges();
}
}
DeleteOnSubmit
方法需要域对象。您的代码将传递一个ID
。此外,您还缺少检查该项是否实际存在的条件
尝试将您的例程改写为以下内容:
foreach (var k in res1)
{
var eigen = from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p;
var item = eigen.FirstOrDefault();
if ( item != null )
{
aspnetdb.Trackpoints.DeleteOnSubmit(item);
aspnetdb.SubmitChanges();
}
}
LINQ to SQL或实体框架?LINQ to SQL。请简要说明LINQ to SQL和实体框架之间的区别好吗?LINQ to SQL是微软在实体框架之前推出的一种ORM,现在已被废弃和过时。LINQ to SQL或实体框架?LINQ to SQL。请简要说明LINQ to SQL和E之间的区别好吗实体框架?LINQ to SQL是Microsoft在实体框架之前的一种ORM,现在已被放弃和废弃。@Kabi:请注意调用
DeleteAllOnSubmit
以进一步简化代码的选项…@Kabi:请注意调用DeleteAllOnSubmit
以进一步简化代码的选项。。。