ado.net entity framework delete rows - c#

I may be completely blind and stupid, but I cannot find any method generated by ADO.NET Entity Data Model that would somehow delete rows from my table. I didn't want to create a custom query. So how do I do that? Please help.
I don't have the method DeleteOnSubmit... don't know why. This is the code I wanted to use.
var deleteOrderDetails =
from details in db.OrderDetails
where details.OrderID == 11000
select details;
foreach (var detail in deleteOrderDetails)
{
db.OrderDetails.DeleteOnSubmit(detail);
}
db.SubmitChanges();

A couple of alterations needed:
db.DeleteObject(detail);
and
db.SaveChanges();
Kindness,
Dan
PS: Have you been using Linq to SQL and then swapped to the Entity Framework?

Here's another way (thanks to this answer)
I assume you have the Orders table, and OrderDetails is related to it via OrderID.
var order = db.Orders.FirstOrDefault(o=> o.OrderID == 11000);
if(order != null)
{
order.OrderDetails.Clear();
db.SaveChanges();
}
This should delete all the order details associated with that order.
edit: fixed the code

Related

How to create a database query with LINQ to erase rows by having a list of ID's and by avoiding loops

I am a newbie with LINQ so I would appreciate if you could explain thoroughly your answer. What I am trying to do is that I have a table called ContentTable. This ContentTable has different columns and rows and one of the columns is using EntityId's.
In my method I receive from somewhere a list of ID's in a List. I don't want to iterate over this list and query the database for each ID because that would be expensive, but I want a query which uses the ID's in the list to match with the EntityID's in the table, and if there is such a match, I erase the whole row from the table. May you kindly help me? Thanks in advance!
You can use Entity Framework Extensions to do that. Something like:
this.Container.Devices.Delete(
o => o.Id == 1,
o => o.Id == 2
);
Some thing like this might help , however if the table is too big (millions) Linq to sql will lock the table. Also for each entity it issues a single T-SQL Delete statement to delete the entity.
public void DeleteContents(List<int> entityIds)
{
using (Yourcontext db = new Yourcontext())
{
IQueryable<ContentTable> contents = db.ContentTable.Where((x) => ids.Contains(x.EntityId));
db.ProductComplianceRules.DeleteAllOnSubmit(contents);
}
}

EF (C#) with tunneling to MySQL - optimising database calls

So I have program to deal with some sort of work in MySQL database. I'm connecting through SSH tunneling with putty (yes, I know launching programs on server itself would be much better but I don't have a choice here).
I have some problems with programs speed. I solved one by adding ".Include(table_name)" but I can't think about a way to do it here.
So purpose of this method is to clean database of unwanted, broken records. Simplified code looks like this:
using (var dbContext = new MyDatabase_dataEntities())
{
List<achievements> achiList = new List<achievements>();
var achievementsQuery = from data in dbContext.achievements
orderby data.playerID
select data;
achiList = achievementsQuery.Skip(counter * 5000).Take(5000).ToList();
foreach (achievements record in achiList)
{
var playerExists = from data in dbContext.players_data
where data.playerID == record.playerID
select data;
if(!playerExists.Any())
{
dbContext.achievements.Remove(record);
}
}
dbContext.SaveChanges();
counter++;
}
So this is built this way because I want to load achievements table then check if achievements have their player in player_data. If such player doesn't exist, remove his achievements.
It is all in do while, so I don't overload my memory by loading all data at once.
I know the problem is with checking in database in foreach steps but I can't figure out how to do it without it. Other things I tried generated errors either because EF couldn't translate it into SQL or exceptions were thrown when trying to access non-existing entity. Doing it in foreach bottlenecks whole program probably because of ping to the server.
I will need similar thing more often so I would be really gratefull if anyone could help me with making it so there is no need to call to database in "foreach". I know I could try to load whole players_data table and then check for Any(), but some tables I need it on are too big for that.
Oh, and turning off tracking changes doesn't help at this point because it is not what slows the program.
I would be gratefull for any help, thanks in advance!
EDIT: Mmmm, is there a way to get achievements which doesn't have player_data corresponding to them through one query using associations? Like adding to achievements query something like:
where !data.player_data.Exists()
Intellisense shows me that there is nothing like Exists or Any to use at this point. Is there any trick similar to this? It would definitely deal with the problem I have with speed there since database call in foreach wouldn't be needed.
If you want to delete achievements that don't have corresponding user records, then you can user a SQL query below:
DELETE a
FROM `achievements` a
LEFT JOIN `user` AS u
ON u.`playerID` = a.`playerID`
WHERE u.`playerID` IS NULL;
SQL query will be an order of magnitude faster than Entity Framework.
If you want to do that in the application, you can use the following code that uses LINQ to Entities and LINQ extensions methods. I assume you have a foreign key for player_data in achievements table so Entity Framework generates player_data lazy property for your achievements entity:
using (var dbContext = new MyDatabase_dataEntities())
{
var proceed = true;
while (proceed)
{
// Get net 1000 entities to delete
var entitiesToDelete = dbContext.achievements
.Where(x => x.players_data == null)
.Take(1000)
.ToList();
dbContext.achievements.RemoveRange(entitiesToDelete);
dbContext.SaveChanges();
// Proceed if deleted entities during this iteration
proceed = entitiesToDelete.Count() > 0;
}
}
If you prefer to use LINQ query syntax instead of extension methods, then your code will look like:
using (var dbContext = new MyDatabase_dataEntities())
{
var proceed = true;
while (proceed)
{
// Get net 1000 entities to delete
var query = from achievement in dbContext.achievements
where achievement.players_data == null
select achievement;
var entitiesToDelete = query.ToList();
dbContext.achievements.RemoveRange(entitiesToDelete);
dbContext.SaveChanges();
// Proceed if deleted entities during this iteration
proceed = entitiesToDelete.Count() > 0;
}
}

How can I make this LinqToSQL query work? (SqlExecption)

The following code gives me an SqlException: Invalid object name 'dbo.studentsCourses'
OO theCourse = subject.Course;
var students = dc.studentsCourses.Where(x => x.course == theCourse).Select(x => x.student);
I tried the following code instead but I also get an Exception.
My original question was asked on Aardvark and can be read bellow:
var allStudents = from s in dc.students select s;
List thestudents = new List();
foreach (student s in allStudents)
{
if (s.courses.Contains(theCourse))
{
thestudents.Add(s);
}
}
I did a right click, "run custom tool" on my dbml and checked my names of my tables and entities. The project compiles but I get an Exception at runtime on this line:
"if (s.courses.Contains(theCourse))"
Any ideas?
Original question on Aardvark:
How do I do a LinqToSQL query that
gives me this: I want to select all
students that attended a certain
lesson. The lesson is from a certain
course. So select the course the
lesson is from. Now select all the
students that are following that
course. There is a many-to-many
relationship between the students and
the courses table in my DB. I already
extended my LINQ entities to be able
to select student.Courses and
course.Students using this method:
http://www.codeproject.com/KB/linq/linq-to-sql-many-to-many.aspx
Your link to sql classes don't match your db schema or your db does not contain a table or view called studentcourses. You need to adjust either your classes or db so they match.
You could start debugging this problem by visualizing the query that is generated by the LinqToSQL. The Gu has written a blogpost on this a while ago:
http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx
Just copy/paste the query in your favourite database management application and run it against the database. It should become clear what the error is. If there are still some crazy things happening, just update your question?
Hope this helps!
First check your database to see if there is really a table or view name studentsCourses.
If there is then try to regenerate to dbml file and then try again.
I'm not sure... but you may try this one:
var xxx = dc.Include("studentsCourses")
.studentsCourses
.Where(x => x.course == theCourse)
.Select(x => x.student)
.ToList();

How to update with Linq-To-SQL?

I need to update values but I am looping all the tables values to do it:
public static void Update(IEnumerable<Sample> samples
, DataClassesDataContext db)
{
foreach (var sample in db.Samples)
{
var matches = samples.Where(a => a.Id == sample.Id);
if(matches.Any())
{
var match = matches.First();
match.SomeColumn = sample.SomeColumn;
}
}
db.SubmitChanges();
}
I am certain the code above isn't the right way to do it, but I couldn't think of any other way yet. Can you show a better way?
Yes, there is a simpler way. Much simpler. If you attach your entities to the context and then Refresh (with KeepCurrentValues selected), Linq to SQL will get those entities from the server, compare them, and mark updated those that are different. Your code would look something like this.
public static void Update(IEnumerable<Sample> samples
, DataClassesDataContext db)
{
db.Samples.AttachAll(samples);
db.Refresh(RefreshMode.KeepCurrentValues, samples)
db.SubmitChanges();
}
In this case, Linq to SQL is using the keys to match and update records so as long as your keys are in synch, you're fine.
With Linq2Sql (or Linq to Entities), there is no way* to update records on the server without retrieving them in full first, so what you're doing is actually correct.
If you want to avoid this, write a stored procedure that does what you want and add it to your model.
I'm not entirely sure if that was your intended question however :)
*: There are some hacks around that use LINQ to build a SELECT statement and butcher the resulting SELECT statement into an UPDATE somehow, but I wouldn't recommend it.

How do you retrieve records and all child records in one database hit in ADO.NET Entities?

I would like to make one database call to retrieve the following data, but I'm struggling to figure out what the LINQ should look like. Here's my current implementation (I know it's bad!!):
var photos = from photo in entitiesContext.Photo
join pg in entitiesContext.PhotoGallery on photo.PhotoGallery.PhotoGalleryID equals pg.PhotoGalleryID
where pg.PhotoGallery == photoGalleryID
select photo;
var photoList = photos.ToList();
foreach (var photoForLoading in photoList)
{
photoForLoading.UserReference.Load();
photoForLoading.PhotoComments.Load();
foreach (var comment in photoForLoading.PhotoComment)
{
comment.UserReference.Load();
}
}
return photoList;
So as you can see above I want to retrieve:
All the photos from a specific photo gallery:
The user details on each photo
The comments on each photo
The user details on each comment
How do I do this in LINQ with ADO.NET Entities Framework?
Cheers,
Ash.
Use the .Include method to load the related entities. For example:
from photo in entitiesContext.Photo
.Include("UserReference")
.Include("PhotoComments")
etc...
When creating your ObjectQuery, call the Include method, passing in the name of the subentity that you want to load automatically. You can chain calls to Include if you have multiple subentities that you want to load.
See this article for more information.

Categories

Resources