How to update linq query result - c#

I will explain my issue using example.
lets say I have linq query result.
var result1=from c in client
select new my_type
{
...
stockDesctiption=??
};
We will say Client has filed called stockId. this is the same as stockId in the dammadgeStockHistory table. these table are not connected in any foreign key constrain.
if i need to get the dammadgeStockHistory.stockDescrption for each client how to do this.

Join tables by this field (foreign key constraint is not required for that):
var result1 = from c in client
join dsh in dammadgeStockHistory
on c.stockId equal dsh.stockId
select new my_type
{
stockId = c.stockId,
// ...
stockDesctiption = dsh.stockDescrption
};
UPDATE If you want to do 'left join':
var result1 = from c in client
join dsh in dammadgeStockHistory
on c.stockId equal dsh.stockId into g
from cdsh in g.DefaultIfEmpty()
select new my_type
{
stockId = c.stockId,
// ...
stockDesctiption = cdsh == null ? null : dsh.stockDescrption
};

Related

How do I change SQL Left Join to Lambda expression in C#?

I have three tables and one input value. As a first step, based on the #Input, I need to fetch DSType from DSTypes table. Now again I need to compare DSType of DSTypes with RTInput table's IType column value. If RTInput table has matching records then need to fetch the ID column value alone otherwise NULL should be assigned.
I achieved this logic in SQL but unable to achieve the same in Lambda expression.
I tried some code from google but that is not returning correct value.
DECLARE #ID
#ID = SELECT ID FROM DSMaster Where DSTId = #Input
SELECT RTI.ID FROM DSTypes(NOLOCK) DST
LEFT JOIN RTInput(NOLOCK) RTI
ON RTRIM(LTRIM(DST.DSType)) = RTRIM(LTRIM(RTI.IType))
WHERE DST.ID = #ID
Lambda expression which I tried:
using (BEContext beContext = new BEContext())
{
var mData = beContext.DSMaster.Where(r => r.DSTId = inputvalue);
var Id = beContext.RTInput.Join(beContext.DSTypes.Where(dst => dst.ID == mData.Id )).Select(z => z.ID).FirstOrDefault();
}
I think this may help.
using {BEContext beContext = new BEContext()){
var mData = (from p in beContext.DSMaster.Where(r=>r.DSTId == inputvalue)
join pr in beContext.RTInput on p.Id equals dst.ID
select new {
//select what you want
}).FirstOrDefault();

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...
};

left join in Linq query

I'm trying to do a left join, not an inner join in a linq query. I have found answers related to using DefaultIfEmpty() however I can't seem to make it work. The following is the linq query:
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id
where a.Table1_id == id
orderby a.sort descending
group e by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
The query only gives me the rows from table 1 that have a corresponding record in table 2. I would like every record in table 1 populated into MyObject and a list of 0-n corresponding records listed in manySubObjects for each MyObject.
UPDATE:
I tried the answer to the question that is a "possible duplicate", mentioned below. I now have the following code that does give me one record for each item in Table1 even if there is no Table2 record.
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id into j1
from j2 in j1.DefaultIfEmpty()
where a.Table1_id == id
orderby a.sort descending
group j2 by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
However, with this code, when there is no record in table2 I get "manySubObject" as a list with one "SubObject" in it with all null values for the properties of "SubObject". What I really want is "manySubObjects" to be null if there is no values in table2.
In reply to your update, to create the null listing, you can do a ternary in your assignment of manySubObjects.
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects =
(from g in ga select g).FirstOrDefaut() == null ? null :
(from g in ga select new SubObject {
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
Here is a dotnetfiddle that tries to do what you're attempting. https://dotnetfiddle.net/kGJVjE
Here is a subsequent dotnetfiddle based on your comments. https://dotnetfiddle.net/h2xd9O
In reply to your comments, the above works with Linq to Objects but NOT with Linq to SQL. Linq to SQL will complain that it, "Could not translate expression ... into SQL and could not treat as a local expression." That's because Linq cannot translate the custom new SubObject constructor into SQL. To do that, you have to write more code to support translation into SQL. See Custom Method in LINQ to SQL query and this article.
I think we've sufficiently answered your original question about left joins. Consider asking a new question about using custom methods/constructors in Linq to SQL queries.
I think the desired Result that you want can be given by using GroupJoin()
The code Below will produce a structure like so
Field1, Field2, List < SubObject > null if empty
Sample code
var query = dc.Table1.Where(x => Table1_id == id).OrderBy(x => x.sort)
.GroupJoin(dc.Table2, (table1 => table1.Table1_id), (table2 => table2.Table2_id),
(table1, table2) => new MyObject
{
field1 = table1.Field1,
field2 = table1.Field2,
manySubObjects = (table2.Count() > 0)
? (from t in table2 select new SubObject { fielda = t.fielda, fieldb = t.fieldb}).ToList()
: null
}).ToList();
Dotnetfiddle link
UPDATE
From your comment I saw this
ga.Select(g = > new SubObject(){fielda = g.fielda, fieldb = g.fieldb})
I think it should be (depends on how "ga" is built)
ga.Select(g => new SubObject {fielda = g.fielda, fieldb = g.fieldb})
Please update your question with the whole query, it will help solve the issue.
** UPDATE BIS **
sentEmails = //ga.Count() < 1 ? null :
//(from g in ga select g).FirstOrDefault() == null ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Should be:
sentEmails = //ga.Count() < 1 ? null :
((from g in ga select g).FirstOrDefault() == null) ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Checks if the group has a First, if it doesn't the group doesn't have any records so the Action.Name for a Time Stamp has no emails to send. If the First isn't null the loop throw the group elements and create a list of Email,
var results =
(
// Use from, from like so for the left join:
from a in dc.Table1
from e in dc.Table2
// Join condition goes here
.Where(a.Id == e.Id)
// This is for the left join
.DefaultIfEmpty()
// Non-join conditions here
where a.Id == id
// Then group
group by new
{
a.Field1,
a.Field2
}
).Select(g =>
// Sort items within groups
g.OrderBy(item => item.sortField)
// Project required data only from each item
.Select(item => new
{
item.FieldA,
item.FieldB
}))
// Bring into memory
.ToList();
Then project in-memory to your non-EF-model type.

LINQ query returning multiple tables

I have the following code:
MyDataContext dc = new MyDataContext();
IQueryable<Table1> q1 =
from n in dc.Table1
select n
What I want to be able to do is to join a second table, so:
var qry =
from n in dc.Table1
join r in dc.Table2 on n.Key equals r.Key
select new { n, r };
This returns me a type of IQueryable<anonymous>. What I now want to do is extract Table1 and Table2. For example (this obviously doesn't work):
IQueryable<Table1> q1 = qry.Table1
IQueryable<Table2> q2 = qry.Table2
Is there a way to do this?
You want to do something like this?
IQueryable<Table1> q1 = qry.Select(x => x.n);
IQueryable<Table2> q2 = qry.Select(x => x.r);
Sure there is:
IQueryable<Table1> q1 = qry.Select(a => a.n);
IQueryable<Table2> q2 = qry.Select(a => a.r);
You can define foreign keys to your tables (on the respective keyfields) and add associations for them to your model clases (ideally via the LINQ-to-SQL designer).
Then you can do:
IQueryable<Table1> items1 = dc.Table1;
foreach (var item1 in items1)
{
var items2 = item1.Table2s; // naming might differ
}
The drawback with doing it that way, is that, even with DataLoadOptions, L2S will make this very expensive. Querying Table2 for every row in the Table1 result set.

Insert row into table that has FK obtained from another table - linq -c#

I have 2 tables, Clients and ClientInterests. The PK/FK being ClientID of type GUID
This is my Linq, where I want to insert into the ClientIneterests table
ClientInterestRegistration clientRegisteration = new ClientInterestRegistration
{
ClientID = (from v in DB.Clients
where v.Email.Equals(EmailAddress)
select new {v.ClientID}).Single(),
ClientInterest = SelectedInterests,
..
};
Error received is:
Cannot implicitly convert type System.Linq.IQueryable<AnonymousType#1> to System.Guid
First, consider removing new {...} from the query and changing it to:
ClientID = (from v in DB.Clients
where v.Email.Equals(EmailAddress)
select v.ClientID).Single()
What you are doing is to create a new structure with the ClientID as its property.
However, you shouldn't work directly with the key column at all. Try setting the Client directly to the object:
Client = (from v in DB.Clients
where v.Email.Equals(EmailAddress)
select v).Single()

Categories