使用LINQ删除记录时出错

时间:2012-07-02 10:10:47

标签: 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();
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)'的最佳重载方法匹配有一些无效的参数

我该怎么办?

3 个答案:

答案 0 :(得分:5)

使用此:

var eigen = (from p in aspnetdb.Trackpoints
            where p.RouteFK == k
            select p).First();

或更短的内容:

var eigen = aspnetdb.Trackpoints.First(p => p.RouteFK == k);

因为它返回Trackpoint

当您select p.TrackPointId返回Int时。


var r = from r in aspnetdb.Routes
        join p in aspnetdb.Trackpoints on p.RouteId equals r.RouteFK
        where r.UserId == UID
        select p;

foreach (var x in r)
{
    aspnetdb.Trackpoints.DeleteOnSubmit(x);
}
aspnetdb.SubmitChanges();

答案 1 :(得分:2)

问题是您只是选择ID,然后与方法签名不匹配。我实际上将您的代码更改为:

var entity = aspnetdb.Trackpoints.Where(p => p.RouteFK == k).Single();
aspnetdb.Trackpoints.DeleteOnSubmit(entity);

(当你将select子句更改为select p时,使用查询表达式变得毫无意义 - 一旦你使用了方法调用语法,它就有意义了在同一声明中调用SingleFirst。根据abatishchev的回答,这也可以是aspnetdb.Trackpoints.Single(p => p.RouteFK == k)。)

顺便说一下,假设您确实为给定的RouteFK提供了1个(并且只有1个)实体。

在单个查询中选择 all 要删除的实体可能实际上更好。例如:

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选择”问题。)

答案 2 :(得分:1)

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();
            }

        }