I try to change a SQL Delete command into LINQ. this is my SQL Command:
DELETE FROM [TrackPoints]
WHERE [RouteFK] IN (SELECT RouteId
FROM Routes
WHERE UserId = @UserId)
and this is the LINQ code that I've written:
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();
}
but in this line I have an error:
aspnetdb.Trackpoints.DeleteOnSubmit(eigen.First());
that said:
The best overloaded method match for 'System.Data.Linq.Table.DeleteOnSubmit(LINQ_Test.Trackpoint)' has some invalid arguments
What should I do?
Use this:
var eigen = (from p in aspnetdb.Trackpoints
where p.RouteFK == k
select p).First();
or what is shorter:
var eigen = aspnetdb.Trackpoints.First(p => p.RouteFK == k);
because it returns Trackpoint
While your select p.TrackPointId
returns 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();
The problem is that you're just selecting the ID, which then doesn't match the method signature. I'd actually change your code to:
var entity = aspnetdb.Trackpoints.Where(p => p.RouteFK == k).Single();
aspnetdb.Trackpoints.DeleteOnSubmit(entity);
(By the time you've change the select
clause to just select p
it becomes pointless to use a query expression - and once you're using the method-call syntax, it makes sense to call Single
or First
in the same statement. As per abatishchev's answer, this could also be aspnetdb.Trackpoints.Single(p => p.RouteFK == k)
.)
This assumes you've definitely got 1 (and only 1) entity for the given RouteFK, by the way.
It might actually be rather better to select all the entities you want to delete in a single query. For example:
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();
Or if you've got your joins set up in your model correctly, you can probably get rid of the explicit join:
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();
In both cases, you can avoid doing nearly as many queries. (You avoid an "n+1 selects" problem.)
The DeleteOnSubmit
method expects the domain object. Your code passes an ID
instead. Also, you lack a condition to check whether the item actually exists.
Try to rewrite your routine to something like:
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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.