DeleteObject from multiple tables - c#

I am trying to delete the movie from rentals table if it is selected from the listbox and it is working but i also need to remove datas connected to the movie from rentingpeople table
Rentals table contains the movieid which is in the listobox and personid which can be also found in rentingpeople and should get deleted the full row if they matches.
var search = (from g in db.Rentals where g.Movietitle == (string)lBfilmlista.SelectedValue select g).First();
foreach (var c in db.Rentingpeople where c.personid==search.personid).First();
{
db.Rentingpeople.DeleteObject(c);
}
db.Rentals.DeleteObject(search);
db.SaveChanges();
there is code error at where c.personid==search.personid ) ; expected

Problem is with First at the end of foreach loop, and also mixing query syntax with method syntax.
So your code should be:
var search = (from g in db.Rentals where g.Movietitle == (string)lBfilmlista.SelectedValue select g).First();
var rowsToBeDeleted = db.Rentingpeople.Where(c=> c.personid==search.personid).ToList();
foreach (var item in rowsToBeDeleted)
{
db.Rentingpeople.DeleteObject(item);
}
db.Rentals.DeleteObject(search);
db.SaveChanges();
You can also setup Cascade on Delete rules for your tables.

Related

How to get two table value using Linq

I have two table one is Administrator table and another is Teacher table .
I want to display these both tables values in single Gridview .
I have make id as a primary key in Administrator table and make this tech_id as foreign key in Teacher table .
Now how to get these table values together in single gridview as shown in pic
Now please any body help me how to get these two value together using Linq .
I have try but I can't make any more
private void loadgri()
{
StudentDatabaseEntities empl = new StudentDatabaseEntities();
var query=from g in empl.Teachers
join m in empl.Administrators on g.id equals m.id
where m.username=="cs"
select new{
Name = g.username,
};
}
You don't need a join if you have already a navigation-property:
var query= from t in empl.Teachers
where t.Administrator.username == "cs"
select new { Teacher = t.username, Administrator = t.Administrator.username };
This is just an example, but you see that you can access all properties of both entities.
Don’t use Linq’s Join. Navigate!
To show all the teachers and their administrator, you don't have to use "join", you could just use the navigation property:
var query = from g in empl.Teachers
where g.Administrator.username=="cs"
select new {
Teacher_Id = g.Id,
Teacher_Name = g.username,
Administrator_Id = g.Id,
Administrator_Name = g.Administrator.username,
//etc...
};

How to delete multiple data using entity framework and asp.net?

Hi I'm now learning about entity framework and still a beginner. Now, I've been having a problem with deleting multiple data in my database. Here is a piece of my database:
Please click to see the image for database
For example i wanted to delete all data that has a brandId of 2. I tried using this code:
int brandId = (from i in context.brands where i.name == name.Text select i.brandId).First();
var bay2 = (from g in context.logoes where brandId == g.brandId select g).FirstOrDefault();
if (bay2 != null)
{
context.logoes.Remove(bay2);
context.SaveChanges();
}
But it only deletes one data, which is logoId 3. It did not delete logoId 4. What am i doing wrong in my query? How to delete all data that has brandId 2 using entity framework?
This line is pulling only one object:
var bay2 = (from g in context.logoes where brandId == g.brandId select g).FirstOrDefault();
Because of the FirstOrDefault.
Remove the FirstOrDefault. Then use RemoveRange:
var bay2 = (from g in context.logoes where brandId == g.brandId select g).FirstOrDefault();
if (bay2.Any())
{
context.logoes.RemoveRange(bay2);
context.SaveChanges();
}
Try to use .ToList() method instead of First(). Then Iterate over this for example list using foreach and delete these objects, or delete whole range.

Searching through SQL Table (LINQ or SqlCommand)

Im trying to search a item table, there is an id, name and oldId (can be null)
When an item is updated a new row is created with the new data, and the old id of the item is set to the new rows OldId field.
But i cant figgure out how to show the latest revision of the item and those who are unedited during search.
var q = from i in Items where i.Name.Contains(x) select i;
Ideas?
If I understand your question correctly, each row whose ID is not used in any other row in the OldId column is the latest revision of its item.
This would lead to the following:
var latestRevisions = Items.Where(x => !Items.Any(y => y.OldId == x.Id));
In SQL, I would write it like this:
SELECT
i.*
FROM
items i
LEFT OUTER JOIN items i2
ON i.item_id = i2.old_item_id
WHERE
i2.item_id IS NULL
;

Linq2SQL: Select only some columns, but still able to submit changes

I need to update a column in a table which contains a lot of rows. Each row has a some large TEXT columns in it, which i do not need for my update.
I'm using LinqPAD, and this is roughly, what i wanna do:
(from s in Table
where s.FK_ID == null
select new{s.FK_ID, s.Datum, s.PBNummer}).ToList()
.ForEach(s => s.FK_ID = new Guid(...some new guid here...));
SubmitChanges();
This does not compile, as the properties of an anonymous class type are read-only.
If I do
(from s in Table
where s.FK_ID == null
select s).ToList()
then I can update and save, but all columns are loaded, which takes a very long time and causes memory problems.
Is there a way to only load some columns but still have an object that i can update and save using SubmitChanges? Or do i have to switch to SQL statements?
Way to update specific columns of a database record in Linq to SQL is to create a View on the table containing large columns, and only include the “short” columns:
CREATE VIEW [dbo].[V_FooMax] AS
SELECT OID, ID
FROM dbo.FooMax
Since views based on single tables are updatable, an update on the view is performed as an update on the table:
using (var database = new DataContext())
{
var fooView = database.V_FooMaxes
.Where(foo => foo.OID == OID).FirstOrDefault();
fooView.ID = newID;
database.SubmitChanges();
}
Reference: http://devio.wordpress.com/2011/01/15/updating-a-single-column-in-linq-to-sql-using-a-view/
Also you can look at: http://devio.wordpress.com/2011/01/16/updating-a-single-column-in-linq-to-sql-summary/
Firstly, if you don't have a primary key in the database, then you wouldn't be able to update via Linq-To-Sql. If you have a primary key, but just don't know which it is, you can find it in Linqpad by doing something like
var table = (from t in Mapping.GetTables()
where t.TableName == "[Table]" select t).SingleOrDefault();
(from dm in table.RowType.DataMembers
where dm.DbType != null && dm.IsPrimaryKey
select dm.Name)
.Dump("Primary Key");
Once you know the primary key, you can do something like the following, (I'm assuming the primary key is called Id)
var oldList = (from s in Table
where s.FK_ID == null
select new{s.Id , s.FK_ID, s.Datum, s.PBNummer}).ToList() ;
This is similar to your query, except I have added the primary key
foreach(var r in oldList)
{
Table t = new Table();
t.Id = r.Id ;
Table.Attach(t);
t.FK_ID = new Guid(...some new guid here...));
}
SubmitChanges();

Which model is the fastest using linq, foreign key relationships or local lists?

Some basics
I have two tables, one holding the users and one holding a log with logins.
The user table holds something like 15000+ users, the login table is growing and is reaching 150000+ posts.
The database is built upon SQL Server (not express).
To administer the users I got a gridview (ASPxGridView from Devexpress) that I populate from an ObjectDatasource.
Is there any general do’s and donts I should know about when summarizing the number of logins a user made.
Things are getting strangely slow.
Here is a picture showing the involved tables.
I’ve tried a few things.
DbDataContext db = new DbDataContext();
// Using foregin key relationship
foreach (var proUser in db.tblPROUsers)
{
var count = proUser.tblPROUserLogins.Count;
//...
}
Execution time: 01:29.316 (1 minute and 29 seconds)
// By storing a list in a local variable (I removed the FK relation)
var userLogins = db.tblPROUserLogins.ToList();
foreach (var proUser in db.tblPROUsers)
{
var count = userLogins.Where(x => x.UserId.Equals(proUser.UserId)).Count();
//...
}
Execution time: 01:18.410 (1 minute and 18 seconds)
// By storing a dictionary in a local variable (I removed the FK relation)
var userLogins = db.tblPROUserLogins.ToDictionary(x => x.UserLoginId, x => x.UserId);
foreach (var proUser in db.tblPROUsers)
{
var count = userLogins.Where(x => x.Value.Equals(proUser.UserId)).Count();
//...
}
Execution time: 01:15.821 (1 minute and 15 seconds)
The model giving the best performance is actually the dictionary. However I you know of any options I'd like to hear about it, also if there's something "bad" with this kind of coding when handling such large amounts of data.
Thanks
========================================================
UPDATED With a model according to BrokenGlass example
// By storing a dictionary in a local variable (I removed the FK relation)
foreach (var proUser in db.tblPROUsers)
{
var userId = proUser.UserId;
var count = db.tblPROUserLogins.Count(x => x.UserId.Equals(userId));
//...
}
Execution time: 02:01.135 (2 minutes and 1 second)
In addition to this I created a list storing a simple class
public class LoginCount
{
public int UserId { get; set; }
public int Count { get; set; }
}
And in the summarizing method
var loginCount = new List<LoginCount>();
// This foreach loop takes approx 30 secs
foreach (var login in db.tblPROUserLogins)
{
var userId = login.UserId;
// Check if available
var existing = loginCount.Where(x => x.UserId.Equals(userId)).FirstOrDefault();
if (existing != null)
existing.Count++;
else
loginCount.Add(new LoginCount{UserId = userId, Count = 1});
}
// Calling it
foreach (var proUser in tblProUser)
{
var user = proUser;
var userId = user.UserId;
// Count logins
var count = 0;
var loginCounter = loginCount.Where(x => x.UserId.Equals(userId)).FirstOrDefault();
if(loginCounter != null)
count = loginCounter.Count;
//...
}
Execution time: 00:36.841 (36 seconds)
Conclusion so far, summarizing with linq is slow, but Im getting there!
Perhaps it would be useful if you tried to construct an SQL query that does the same thing and executing it independently of your application (in SQL Server Management Studio). Something like:
SELECT UserId, COUNT(UserLoginId)
FROM tblPROUserLogin
GROUP BY UserId
(NOTE: This just selects UserId. If you want other fields from tblPROUser, you'll need a simple JOIN "on top" of this basic query.)
Ensure there is a composite index on {UserId, UserLoginId} and it is being used by the query plan. Having both fields in the index and in that order ensures your query can run without touching the tblPROUserLogin table:
Then benchmark and see if you can get a significantly better time than your LINQ code:
If yes, then you'll need to find a way to "coax" the LINQ to generate a similar query.
If no, then you are already as fast as you'll ever be.
--- EDIT ---
The follwing LINQ snippet is equivalent to the query above:
var db = new UserLoginDataContext();
db.Log = Console.Out;
var result =
from user_login in db.tblPROUserLogins
group user_login by user_login.UserId into g
select new { UserId = g.Key, Count = g.Count() };
foreach (var row in result) {
int user_id = row.UserId;
int count = row.Count;
// ...
}
Which prints the following text in the console:
SELECT COUNT(*) AS [Count], [t0].[UserId]
FROM [dbo].[tblPROUserLogin] AS [t0]
GROUP BY [t0].[UserId]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
--- EDIT 2 ---
To have the "whole" user and not just UserId, you can do this:
var db = new UserLoginDataContext();
db.Log = Console.Out;
var login_counts =
from user_login in db.tblPROUserLogins
group user_login by user_login.UserId into g
select new { UserId = g.Key, Count = g.Count() };
var result =
from user in db.tblPROUsers
join login_count in login_counts on user.UserId equals login_count.UserId
select new { User = user, Count = login_count.Count };
foreach (var row in result) {
tblPROUser user = row.User;
int count = row.Count;
// ...
}
And the console output shows the following query...
SELECT [t0].[UserId], [t0].[UserGuid], [t0].[CompanyId], [t0].[UserName], [t0].[UserPassword], [t2].[value] AS [Count]
FROM [dbo].[tblPROUser] AS [t0]
INNER JOIN (
SELECT COUNT(*) AS [value], [t1].[UserId]
FROM [dbo].[tblPROUserLogin] AS [t1]
GROUP BY [t1].[UserId]
) AS [t2] ON [t0].[UserId] = [t2].[UserId]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
...which should be very efficient provided your indexes are correct:
The second case should always be the fastest by far provided you drop the ToList() so counting can be done on the database side, not in memory:
var userId = proUser.UserId;
var count = db.tblPROUserLogins.Count(x => x.UserId == userId);
Also you have to put the user id into a "plain" primitive variable first since EF can't deal with mapping properties of an object.
Sorry, doing this blind since I'm not on my normal computer. Just a couple of questions
do you have an index on the user id in the logins table
have you tried a view specifically crafted for this page?
are you using paging to get the users, or trying to get all counts at once?
have you run sql profiler and watched the actual sql being sent?
Does something like this work for you?
var allOfIt = from c in db.tblProUsers
select new {
User = c,
Count = db.tblProUserLogins.Count(l => l.UserId == c.UserId)
}
.Skip(pageSize * pageNumber)
.Take(pageSize) // page size

Categories