linq query for returning single row - c#

For any transaction happening a row is inserted into my table.
i have table(Transactions)like following
ID----------Amount
1------------150.00
2----------- 246.00
3----------- 100.00
4----------- 201.00
If the above transaction is happening with multiple tender types(cash,creditcard etc),for each tender type a row is inserted into another table.
This new table(Tender) looks like following
ID---- TenderType----- TransactionId
1----------- 10 ---- 1
2------------ 20---- 2
3-------------10-----2
The above tells that,the 1st Transaction(from Transactions table,amount 150.00) happened with only one tender type(10).So one one row in Tender table.
The 2nd transaction(amount 246.00) happened with two tender types(10 and 20).So two rows in Tender table.
Now i want the output as
Amount------ TenderType
150.00 ------ 10
246.66-------10/20
Now i am writing a linq query in c# and it is returning two rows if there are multiple rows in Tender table for each Amount in Transaction table.
My query look like following:
(from T in context.Transactions
join TT in context.TenderType on T.ID equals TT.TransactionId
select new myModel
{
Amount = T.Amount,
TenderType = TT.TenderType
}).ToList();
For this query my output looks like this:
Amount------ TenderType
150.00 ------ 10
246.66-------10
246.66-------20
But my output should be like this :
Amount------ TenderType
150.00 ------ 10
246.66-------10/20
How to modify my query to achieve this ?
Thanks in advance.

It sounds like you can have a one to many association from Transaction to Tender.
public class Transaction {
public int ID { get; set; }
public double Amount { get; set; }
public virtual ICollection<Tender> Tenders { get; set; }
}
from T in context.Transactions
select new {
Amount = T.Amount,
TenderTypes = T.Tenders.Select(t => t.TenderType)
}

Try this
(from T in context.Transactions
select new myModel
{
Amount = T.Amount,
TenderType = context.TenderType.Where(x=>x.TransactionId==T.ID).Select(x=>x.TenderType).FirstOrDefault()
}).ToList();

Try this:-
var result= (from T in context.Transactions
join TT in context.TenderType
on T.ID equals TT.TranscationID into g
select new
{
Amount = t.Amount,
TenderType = String.Join("/",g.Select(x => x.TenderTypeID))
}).Where(x => !String.IsNullOrEmpty(x.TenderType));

Related

EF Core left join with count

i have got 3 tables on MySql database. i want to do left join between this 3 tables and count with group by.
City Table
Id
Name
School Table
Id
CityId
Name
Student Table
Id
SchoolId
Name
/* MySql raw query like this: */
select Count(tstudent.id) as StudentCount, tcity.Id, tcity.Name
from City tcity
left join School tschool on tcity.Id = tschool.CityId
left join Student tstudent on tschool.Id = tstudent.SchoolId
group by tcity.Id;
With EF Core i try like this:
class CityWithStudentCount {
public int Id { get;set; }
public string CityName { get;set; }
public int StudentCount { get;set; }
}
Ef Core :
var db = new MyDbContext();
var result = (from city in db.City
join school in db.School on city.Id equals school.CityId into tcity
from r1 in tcity.DefaultIfEmpty()
join student in db.Student on school.Id equals student.SchoolId into tschool
from r2 in tschool.DefaultIfEmpty()
select new CityWithStudentCount
{
Id = city.Id,
CityName = city.Name,
StudentCount = tschool.count()
} into s1
group s1 by s1.Id)
.Select(s=>s.ToList())
.ToList();
Result must be like that :
1 City1 10
2 City2 3
3 City3 0
4 City4 0
5 City5 12
How can i do like this query for this result with Entity Framework Core. Thank you.
Your query is wrong.
var result = (from city in db.City
join school in db.School on city.Id equals school.CityId into t1
from school in t1.DefaultIfEmpty()
join student in db.Student on school.Id equals student.SchoolId into t2
from student in t2.DefaultIfEmpty()
group student by new { city.Id,city.Name } into cityGrouped
select new CityWithStudentCount
{
Id = cityGrouped.Key.Id,
CityName = cityGrouped.Key.Name,
StudentCount = cityGrouped.Count(x => x.student != null)
}
.ToList();
Also, I strongly suggest you to use navigation properties instead of manual building joins.

Linq to get complete row based on duplicate values in column

I am looking for a LINQ to use with my datatable and display all the duplicate rows based on certain columns in windows form datagrid view.
The LINQ should give a result similar to the plain old below give SQL.
SELECT *
FROM Table1 t
JOIN ( SELECT Taskid, Studentid, DateChangeid
FROM Table1
GROUP BY Taskid, studentid, datechangeid
HAVING COUNT(*) > 1) temp
ON t.taskid = temp.taskid AND t.studentid= temp.studentid AND t.datechangeid= temp.datechangeid
This should do what you want:
var result =
t.GroupBy(g => new {TaskId = Taskid, StudentId = studentid, DatechangeId = datechangeid})
.Where(g => g.Count > 1)
.ToList();
Now you're joining Table1 on Table1 which isn't needed, just do the filtering on Table1 only.
Now the result will be of type List<IGrouping<'a,Table1>> though because of the anonymous keyselector, you can also define TaskId , StudentId and DateChangeID in a class to get rid of that. For example:
public class Table1GroupKey
{
public int TaskId {get; set;}
public int StudentId {get; set;}
public int DateChangeId {get; set;}
}
Then you can use:
GroupBy(g => new Table1GroupKey { ... })
And your result will be List<IGrouping<Table1GroupKey,Table1>>.
I managed it by writing two linq as given below.
var RepeatedValues = from d in DataTableitems.AsEnumerable()
group d by d.Field<string>("MobileNo") into itemGroup
where itemGroup.Count() > 1
select new { name = itemGroup.Key };
var RepeatedInRows= from d in DataTableitems.AsEnumerable()
join c in RepeatedValues.AsEnumerable() on d.Field<string>
("MobileNo") equals c.name
select d;

Creating a gridview or listview from different sql tables in asp.net

What i aim to achive with this is to have a grid or listview where the colums get data from different sql tabels.
Here are the different tabels
TradeItemIdentification
id GTIN
TradeItemDescriptionInformation
id brandName tradeItemFunctionalName
ClassificationCategory
id additionalClassificationCategoryCode
I don know if it is possible to show a grid with all of these attributes except the id's. What is the smartest way to do achive this, if possible?
They are all linked to this table. With these "many ot many" tabels.
TradeItemBasic
id
TradeItemIdentificationOnTradeItem
tradeItemId identificationId
TradeItemDescriptionInformationsOnTradeItem
tradeItemId descriptionId
And the same for the last table. So they have a connection.
Here is some joins of the tabels that i have made so far.
public List<string> GetAllProductsInfo()
{
var gtins = (from gtinss in _db.TradeItemIdentificationOnTradeItems
join gtin in _db.TradeItemIdentifications on gtinss.tradeItemIdentificationId equals gtin.id
select gtin.gtin);
var brandNames = (from descriptions in _db.TradeItemDescriptionInformationsOnTradeItems
join description in _db.TradeItemDescriptionInformations on descriptions.tradeItemDescriptionInformationId equals description.id
select description.brandName);
var article = (from articleNumbers in _db.ClassificationCategoryOnGDSNTradeItemClassifications
join articleNumber in _db.ClassificationCategories on articleNumbers.gDSNTradeItemClassificationId equals articleNumber.id
select articleNumber.additionalClassificationCategoryCode);
var allInfo = gtins.Concat(brandNames).Concat(article).ToList();
return allInfo;
}
This is what ive got so far, i am no able to get all of the items that i wanted. But when i do it like this the results is not divided in to sections, but instead it is all just gets put out as one long list.
Just join the different tables and select the properties you want to display.
There are two different use cases. If you want to display all lines where some data is missing then use left joins. Else use inner joins (just replace the left join). That reduce your resultset.
Here is an example how to join your tables:
SELECT tib.id, tii.GTIN, tidi.brandName, tidi.tradeItemFunctionalName
FROM TradeItemBasic AS tib
LEFT JOIN TradeItemIdentificationOnTradeItem AS tii2ti ON tib.id = tii2ti.tradeItemId
LEFT JOIN TradeItemIdentification AS tii ON tii.id = tii2ti.identificationId
LEFT JOIN TradeItemDescriptionInformationsOnTradeItem AS tidi2ti ON tib.id = tidi2ti.tradeItemId
LEFT JOIN TradeItemDescriptionInformation AS tidi ON tidi.id = tidi2ti.descriptionId
For the ClassificationCategory you don't post a mapping table, so i remove the selected property.
Hope that helps.
I solved it.
I Made a new C# class. Called ProductInfo that looks like this
public class ProductInfo
{
public ProductInfo()
{
}
public List<string> Gtin { get; set; }
public List<string> BrandName { get; set; }
public List<string> ArticleNr { get; set; }
}
this class takes three types of lists.
And here is the method for getting the specific information from the different classes.
public ProductInfo GetAllProductsInfo()
{
var gtins = (from gtinss in _db.TradeItemIdentificationOnTradeItems
join gtin in _db.TradeItemIdentifications on gtinss.tradeItemIdentificationId equals gtin.id
select gtin.gtin).ToList();
var brandNames = (from descriptions in _db.TradeItemDescriptionInformationsOnTradeItems
join description in _db.TradeItemDescriptionInformations on descriptions.tradeItemDescriptionInformationId equals description.id
select description.brandName).ToList();
var article = (from articleNumbers in _db.ClassificationCategoryOnGDSNTradeItemClassifications
join articleNumber in _db.ClassificationCategories on articleNumbers.gDSNTradeItemClassificationId equals articleNumber.id
select articleNumber.additionalClassificationCategoryCode).ToList();
ProductInfo pr = new ProductInfo { Gtin = gtins, BrandName = brandNames, ArticleNr = article };
return pr;
}
with this method i get three lists from the tabels that i wanted. And after i made the joins i just create a new ProductInfo and add the results to the right lists in the new class.

How can I LINQ outer join two collections?

I have the following query:
var rowData = companies.Select(
t => new CompanyDetail
{
CompanyID = t.Title,
Subjects = subjects.Count ( u => t.RowKey == "0000" + u.PartitionKey)
}).ToList();
public class CompanyDetail
{
[DisplayName("Company")]
public string CompanyID { get; set; }
[DisplayName("Subjects")]
public Int32 Subjects { get; set; }
}
The query output looks like this:
CompanyID Subjects
1 2
2 4
3 1
However I have a problem if the company has no subjects. I would like to see:
CompanyID Subjects
1 2
2 4
3 1
4 0
Is there a way that I can convert this LINQ query into an outer join so it always reports every company and then gives a count of how many subjects are connected through the row and partitionkey connector?
It's hard to answer this without knowing what LINQ provider you are using - your query would work as you expect in LINQ to Objects, for example.
Perhaps it would be worth a try to use an explicit GroupJoin to convince the provider to give you empty groups:
var rowData = from company in companies
join subject in subjects
on company.RowKey equals "0000" + subject.PartitionKey
into companySubjectGroup
select new
{
CompanyID = company.Title,
Subjects = companySubjectGroup.Count()
};

SQL Linq Question

I have the following working TSQL query in ms SQL 2008
SELECT
Date,
COUNT(click) AS clicks,
COUNT(sale) AS sales,
count(lead) as leads
FROM
(
SELECT ClickDate as date ,ID AS click ,CAST(NULL AS int) AS sale , CAST(null as int) as lead
FROM clicks
UNION ALL
SELECT Date,null, ID ,NULL
FROM sales
UNION ALL
SELECT Date,null, NULL ,ID
FROM leads
) t
GROUP BY Date
How would i convert this to LINQ to SQL?
I wrote this LINQ but it doesn't work.
public class mydata
{
public DateTime date { get; set; }
public int? click { get; set; }
public int? sale { get; set; }
public int? lead { get; set; }
}
var clicks = from c in Clicks
select new mydata
{
date = c.ClickDate, click = c.ID, sale = null, lead = null
};
var sales = from s in Sales
select new mydata
{
date = s.Date, click = null, sale = s.ID, lead = null
};
var leads = from l in Leads
select new mydata
{
date = l.Date, click = null, sale = null, lead = l.ID
};
var v = clicks.Concat(sales).Concat(leads);
var res = from x in v
group x by x.date into xg
select new
{
date = xg.Key, clicks = xg.Count(z => z.click != null)
};
}
How do i correct this LINQ query?
Update:
i Modified the LINQ query based on David B recommendation.
i'm still getting the following error:
"All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."
David's correct about the first two issues. For your final problem (3), Count() does not work like it does in SQL. It expects a predicate that returns a bool. Your using it with ints (i.e. z.click, z.sales, etc.)
The problem is that the anonymous types in the projections are not identical... ID is int in one and Nullable<int> in another.
Instead of using an anonymous type in your projections, use this:
public class ConcatTarget
{
public DateTime TheDate {get;set;}
public int? ID {get;set;}
public string sale {get;set;}
public string lead {get;set;}
}
Even though no instances are actually constructed, LinqToSql uses the class's shape to translate the query.
As for Count, perhaps you meant .Count(x => x.Prop != null) ?
Ok, apparently you've hit upon a buggy translation behavior as described here.
What's happening is the sql translator sees the null assignments, and throws them away. This causes an incorrect number of sql columns to be selected between the sets.
Here's a possible workaround:
int? myNull = null;
var clicks =
from c in Clicks
select new mydata
{
date = c.ClickDate,
click = c.ID,
sale = c.ID + myNull,
lead = myNull + c.ID //note - expressions must be unique
};
The basic idea is to create unique expressions the query translator can't throw away. This is harder than it sounds (above is my ninth attempt).
Here's the other two tables:
var sales = from s in Sales
select new mydata
{
date = s.Date,
click = s.ID + myNull,
sale = s.ID,
lead = myNull + s.ID
};
var leads = from l in Leads
select new mydata
{
date = l.Date,
click = l.ID + myNull,
sale = myNull + l.ID,
lead = l.ID
};
If you had more than 2 columns-to-be-nulled, you could resort to subtraction, division, multiplication, etc.

Categories