Linq to Entity use relation of tables fill gridview - c#

I have 3 Tables Customer,CustomerTicket,Ticket
Customer-->ID primary key
CustomerTicket-->ID,TicketNo where ID,TicketNo are foreign-key
Ticket-->TicketNo,Subject where TicketNo primary key
I am using linq to entity and want to show columns like this,
ID TicketNo Subject
1 12 Car
1 18 Home
2 23 Plane
Every unique ID can have Many TicketNo and every TicketNo has one unique Subject
Gridview.DataSource=from customer in entity.Customer
join custicket in entity.CustomerTicket on customer.ID equals custicket.ID .....
I tried code like the above but in the end couldn't understand how to make the table as I want.How will code continue or is there any better way? Also note that entity framework took my CustomerTicket table and add it as navigation property ...

Do the joins, create an anonymous collection with select, create a binding datasource with the collection and set the datasource
var cusList=from customer in entity.Customer
join custicket in entity.CustomerTicket on customer.ID equals custicket.ID
select new
{
custicket.ID,
custicket.ticketno,
ticket.subject
};
var bs = new BindingSource();
bs.DataSource=cusList;
Gridview.DataSource=bs;

Related

LINQ join multiple tables by same column

I have one table Texting, that I need to join with another two tables Student and Staff to search for information about these 2 tables.
Student fields:
Id
Name
... and a bunch of other fields specific to student
Staff fields:
Id
Name
... and a bunch of other fields specific to staff
Texting fields:
Id
PersonId // contains either student ID or staff ID
PersonTypeId // indicates whether PersonId is of type student or staff (student = 1, staff = 2)
Now I need to write a linq query to search the table Texting either by student or staff name but I am stuck on the linq to achieve this.
var query = (from t in texting
join s in studentBo.GetListQuery()
on t.PersonId equals s.Id
join st in staffBo.GetListQuery()
on t.PersonId equals st.Id
where ...
select t);
This joins the tables together but it doesnt care what the PersonId type is so it's all mixed. How do i specify so that it joins the PersonId correctly according to the right PersonTypeId? It seems like nothing else can be appended on the on clause or where clause to make this happen = (.
So you have a name, and you want all Textings that refer to a Student with this name, and all Textings that refer to a member of Staff with this Name.
My advice would be to concat the Student textings with the Staff textings. You could do that in one big LINQ statements, however this would make it quite difficult to understand. So I'll do it in two steps, then Concat it in one query:
const int student = 1;
string name = "William Shakespeare";
var studentTextings = textings.Where(texting => texting.PersonTypeId == student)
.Join(students.Where(student => student.Name == name),
texting => texting.PersonId, // from every Texting take the foreign key
student => student.Id, // from every Student take the primary key
// parameter resultSelector:
// from every texting with its matching student make one new:
(texting, studentWithThisTexting) => new
{
// Select the Texting properties that you plan to use
Id = texting.Id,
...
}
In words: from all Textings, keep only those Textings that refer to a student, so you know that the foreign key refers to a primary key in the table of Students. From all Students keep only those Students that have the requested name.
Join all remaining Textings and the few remaining Students that have this name on primary and matching foreign key.
Do something similar for members of Staff:
const int staff = 2;
var staffTextings = textings.Where(texting => texting.PersonTypeId == staff)
.Join(staffMembers.Where(staffMember => staffMember.Name == name),
texting => texting.PersonId, // from every Texting take the foreign key
staffMember => staffMember.Id, // from every Staff member take the primary key
// parameter resultSelector:
(texting, staffMembers) => new
{
// Select the Texting properties that you plan to use
Id = texting.Id,
...
}
Now all you have to do is Concat these two. Be aware: you can only Concat similar items, so the resultSelector in both Joins should select objects of exactly the same type.
var textingsOfPersonsWithThisName = studentTextings.Concat(staffTextings);
There is room for improvement!
If you look closely, you'll see that the textings table will be scanned twice. The reason for this, is because your database is not normalized.
Can it be, that a Texting for a Student will ever become a Texting for a member of Staff? If not, my advice would be to make two tables: StudentTextings and StaffTextings. Apart from that queries will be faster, because you don't have to check PersonType, this also has the advantage that if later you decide that a StudentTexting differs from a StaffTexting, you can change the tables without running into problems.
If you really think that sometimes you need to change the type of a texting, and you don't want to do this by creating a new texting, you also should have two tables: one with StudentTextings, and one with StaffTextings, both tables having a one-to-one relations with a Texting.
So Students have one-to-many with StudentTextings, which have one-to-one with Textings. Similar for Staff and StaffTextings.
So Student [4] has 3 StudentTextings with Id [30], [34], [37]. Each of these StudentTextings have a foreign key StudentId with value [4]. Each StudentTexting refers to their own Texting with a foreign key: [30] refers to texting [101], so it has foreign key 101, etc.
Now if texting [101] has to become a texting for Staff [7], you'll have to delete the StudentTexting that refers to [101] and create a new StaffTexting that refers to Staff [7] and Texting [101]
By the way, since the combination [StudentId, TextingId] will be unique, table StudentTextings can use this combination as primary key. Similar for StaffTextings
You will have to merge Student and Staff tables, otherwise all your queries will be too complicated, since you will have to use Union
Person
Id
Name
PersonType
Texting
Id
PersonId
and query
var query = (from t in texting
join p in person
on t.PersonId equals p.Id
where ...
select t);
PS if you still want a query with 2 tables instead of one, you will have to post the real code.
You'll need to do these as two separate queries, project to a new type and then union the results. Messy, but here's how.
First get your students:
var textingStudents = (
from s in students
join t in texting on s.Id equals t.PersonId
where t.PersonTypeId == 1
select new { id = s.Id, personTypeId = 1, name = s.Name }).ToList();
Now get your staff in almost the exact same way:
var textingStaff = (
from s in staff
join t in texting on s.Id equals t.PersonId
where t.PersonTypeId == 2
select new { id = s.Id, personTypeId = 2, name = s.Name }).ToList();
Now you can union the two:
var allTextingPeople = textingStudents.Union(textingStaff);
If you need additional properties then add then to the anonymous type declared in the select statement - remember, the type will need to have the same properties in both the textingStudents and textingStaff result. Alternatively, define a class and do a select new MyUnionClass { ... } in both queries.
Edit
You're going to probably get into a world of hurt with the current approach you've outlined. If you're using a relational database (i.e. sql server) you almost certainly are not defining constraints such as foreign keys on your Texting table meaning you'll end up with ID clashes and will definitely end up with bugs later down the road. Best approach is probably to have one table to represent Staff and Student (let's call it Person with a column defining the "type" of person - the column itself will be foreign key link to another table with your list of PersonTypes

Compare two DataTables with several keys and select the rows that are not present in second table

I have two DataTables and I want to select the rows from the first one which are not present in second one, both tables have 3 Keys custnum, shiptonum, connum
For example:
Table Contacts
custnum shiptonum connum column
1 1 1 data1
2 2 2 data2
3 3 3 data3
4 4 4 data4
Table Invitations
custnum shiptonum connum column
1 1 1 data11
3 3 3 data33
I'd like the result to be:
Table Result
custnum shiptonum connum column
2 2 2 data2
4 4 4 data4
I already tried using
var differences = table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);
but it didn't work. For example in my testing in Contacts table I have 14,389 records, in Invitations table I have two records that exist in Contacts table the count after using the abovesolution was 14,389 instead of 14,387 (removing the two records from Invitations table).
You wrote:
I want to select the rows from the first one which are not present in second one
From your example, I see that you don't want to select rows from the first table that are not rows in the second table, but that you only want to take the values of the keys into account:
I want to select all rows from tableA which have keys with values that are not keys from tableB
You didn't define your tables. They might be IQueryable, or IEnumerable, for your LINQ statements there is not a big difference. Try to avoid AsEnumerable, especially if your data source is in a different process, like a database management system. The other process is much more efficient in executing your query than your process. AsEnumerable transports all data from your other process to your process, which is a relatively slow process. Therefore as a rule: Only use AsEnumerable this if you really need to,
The second definition defines clearer what you want: apparently from tableB you only need the keys:
var keysTableB = tableB.Select(row => new
{
CustNum = row.custNum,
ShipToNum = row.shiptonum,
ConNum = row.connum,
});
In words: from every row in tableB make one new object of anonymous type with three properties: CustNum, ShipToNum and ConNum
Select uses lazy execution. No query is executed, only property Expression is changed.
Now you want to keep only the rows from tableA that have a key that is a member of sequence keysTableB: if you want to keep a subset of a sequence, use Where
var result = tableA.Where(row => keysTableB.Contains(new
{
CustNum = row.custNum,
ShipToNum = row.shiptonum,
Connum = row.connum,
}));
In words: from every row in tableB keep only those rows that have a key that is also in keysTableB, using value equality.
TODO: consider concatenating these two LINQ statements into one.I doubt whether this would improve performance. It surely will deteriorate readability of your code, and thus decreases changeability / maintenance / testability.
for (int i=0;i<table1.rows.count;i++)
{
var rowExists = from dr in table2.AsEnumerable()
where dr.Field<typeofcolumn>("colum_name")==table1.Rows[i]["column_name"]
select dr;
if(rowExists.ToList().Count==0)
{
//here u import row table1.rows[i] to new table
}
}

Outerjoin with a table of foreign keys in EF Data-first approach

I have a table Users which contain user information. I have a table Products which contain product information. I have a table called UserProduct which acts as a junction table and whose fields are UserId and ProductId. I am using a Entity Framework database first approach.
I want to outerjoin using Linq to find the following data.
All Users in the Users table.
All Users who have bought a particular product in terms of a Boolean called isPurchased.
My thinking was to left outer join table User with UserProduct and get all users and whether they have a product something like this.
var result = from a in Users
join b in UserProduct(Not available through EF) on a.Id equals b.prodId into group1
from g1 in group1.DefaultIfEmpty()
select new
{
id = g1.Id,
isPurchased = g1.prodId != null
}.ToList();
However in EF mapping, the object UserProduct is not created and so I cannot use it directly in my Linq query? So how do I go about this? Is there a way I can use linq to join tables with the actual table name(UserProduct) instead of joining entities?
Assuming Users contains a property List<Products> products to represent the junction information, and a variable boughtProductId to represent the particular product:
var result = from u in Users
let isPurchased = u.products.Any(p => p.Id == boughtProductId)
select new {
id = isPurchased ? boughtProductId : null,
isPurchased
}.ToList();

Including a second query in Entity Framework LINQ Query

I've got a table "Houses" and "Cats", which contains the columns "Id" and "HouseName" and "Id" and "CatName".
Now I got a table "HouseCatAssignments", where I store the relations between the Cats and the Houses (the Cat can live in more than one house and one house can store more than one cat).
This table looks like:
Id, CatId, HouseId
"CatId" is bound to Cats.Id and HouseId is bound to Houses.Id.
Now I want to display the Table "House" in a datagrid that also contains a field for "CatCount" - a counter for the value of how many cats are living in this house.
How should I now query my tables so I have all the values of "Houses" and an additional Column that contains the Cat-Count for the specific house?
For Entity Framework it should have automatically added navigation properties that allow you to do the following query:
var housesWithCount = context.Houses
.Select( h=> new
{
Id = h.Id,
HouseName = h.HouseName,
CatCount = h.Cats.Count()
});

Combine two or more table into one object

I need to combine two or more table into one object by using C# 4,0... I wrote a class for a table which included simple select selectbyid insert update and update.... it works fine for single table... by the way I have two attribute which specifies table name column name and primarykey... by using all these I can create my simple methods but I need to select and update more table in one object or method... what should I do or what would you suggest about it...
Example:
users and customer table I have foreign keys which defined...
If you`re using linq to sql, you can join the other tables like
var q =
from s in db.Suppliers
join c in db.Customers on s.City equals c.City
select new {
Supplier = s.CompanyName,
Customer = c.CompanyName,
City = c.City
};
as just copy & paste from a sample of MSDN LINQ to SQL: .NET Language-Integrated Query for Relational Data

Categories