advanced projection query - c#

Any better way of doing this
using (var db = new SmartContext())
{
var MyQuery = from idr in db.ID_SB
join tk in db.Track_SB on idr.MB_Track_ID equals tk.MB_TrackID
join talr in db.Track_Album_Reln on tk.MB_TrackID equals talr.MB_Track_ID
join tal in db.Album_SB on talr.MB_AlbumID equals tal.MB_Release_ID
orderby idr.Last_played descending
select new
{
mb = tk.MB_TrackID,
Hash = idr.Hash,
Title = tk.Title,
Album = tal.Album_Name,
Times_Played = idr.Times_played,
Last_Played = idr.Last_played
};
string artist = "";
var list = new[] { new { Hash = "", Title = "", Album = "", Artist = "", Times_Played = "", Last_Played = ""}}.ToList();
list.Clear();
foreach (var q in MyQuery)
{
int i = 0;
var art = db.Track_Artist_Reln.Where(a => a.MB_Track_ID == q.mb);
foreach (var a in art)
{
var tart = db.Artist_SB.Where(ar => ar.MB_Artist_ID == a.MB_ArtistID).Select(ar => ar.Artist_Name);
foreach (var tar in tart)
{ if (i != 0) { artist = artist + ", " + tar; } else { artist = tar; i++; } }
}
list.Add(new
{
Hash = q.Hash.ToString(),
Title = q.Title.ToString(),
Album = q.Album.ToString(),
Artist = artist.ToString(),
Times_Played = q.Times_Played.ToString(),
Last_Played = q.Last_Played.ToString(),
});
}
ListView1.ItemsSource = list;
}
is there any better way for this as it is consuming lot of time
this code serves the purpose
in this i want to retrieve
hash
Title
Albumname
Artist ( containing all the artist for that song in single row field artist)
Times played
Last played
everything i am able to get just by getting join of everything apart from artist name
there are many to may relations
main tables ID_SB, Track_SB, Album_SB, Artist_SB
other are relationship storing the primary keys of both tables

The inner loop can be replaced with using string.Join(…) and .SelectMany() to flatten the nested list (really IEnumerable) into one:
var artist = string.Join(", ",
db.Track_Artist_Reln
.Where(a => a.MB_Track_ID == q.mb)
.SelectMany(a => db.Artist_SB
.Where(ar => ar.MB_Artist_ID == a.MB_ArtistID)
.Select(ar => ar.Artist_Name)));
Instead of converting the enumerable to a List manually you can use .ToList():
var list = MyQuery.Select(q => new{
Hash = q.Hash.ToString(),
Title = q.Title.ToString(),
Album = q.Album.ToString(),
Artist = string.Join(", ",
db.Track_Artist_Reln
.Where(a => a.MB_Track_ID == q.mb)
.SelectMany(a => db.Artist_SB
.Where(ar => ar.MB_Artist_ID == a.MB_ArtistID)
.Select(ar => ar.Artist_Name))),
Times_Played = q.Times_Played.ToString(),
Last_Played = q.Last_Played.ToString(),
}.ToList();

Related

How can I compare a value from List<string> to Project.Models.Class?

I want to retrieve data from Project.Models.transaction_details by using linq, comparing value from list of string (List).
here is my code
List<transaction_details> transactions = new List<transaction_details>();
List<string> date_list = new List<string>();
// date_list output is ["2020-01-01","2020-01-02",2020-01-03",...,"2020-01-31"]
while (sdr.Read())
{
transactions.Add(new transaction_details
{
ID = sdr.GetInt32("ID"),
Transdate = sdr.GetDateTime("Transdate"),
Debit = sdr.GetDecimal("Debit"),
TransactionName =sdr.GetString("TransactionName"),
BranchID = sdr.GetString("BranchID")
});
}
var array1Index = date_list.Select((i, index) => new { Index = index, i = i }).ToList();
List<transaction_details> arrayresult = new List<transaction_details>();
var query1 = from a in array1Index
select transactions.Contains(a.i) == true ? a.i : "";
arrayresult = query1.ToList();
arrayresult.ForEach(x => {
Console.Write(x + " ");
});
My problem is (a.i) is an error.
Cannot convert 'string' to 'Project.Models.transaction_details'.
you probably mean to check the transaction date. try this:
var query1 = from a in array1Index
select transactions.Any(t => t.Transdate == a.i) == true ? a.i : "";
EDIT:
if you want a list of transactions try this:
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate)
select t;
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate);
try this

Merge two Lists of same type with diff values and avoid duplicates

I have two lists of same type with different key value pairs,
List1 has "isPermanent = true" and List2 has false value and also
List1 has an extra key "nextVacationDate".
Im trying to do union of these as below but im afraid I will still get the duplicates because of different values. I need to merge both lists in to one list and order by List1 first (Permanent employees first)..is there a better way to do this using LINQ?
public newList1 List1(string abcd)
{
var result = serviceMethod1(abcd);
var newList1 = new List<emp>();
if (result == null) return null;
newList.AddRange(
result.Select(x => new Model
{
firstName = x.FName,
secondName = x.SName,
address = x.Address,
employeeId = x.EmpId,
isPermanent = true,
nextVacationDate =x.VacDt,
salary = x.Bsalary
}));
return newList1;
}
public newList2 List2(string defg)
{
var result = serviceMethod2(defg);
var newList2 = new List<emp>();
if (result == null) return null;
newList.AddRange(
result.Select(x => new Model
{
firstName = x.FName,
secondName = x.SName,
address = x.Address,
employeeId = x.EmpId,
isPermanent = false,
salary = x.Bsalary
}));
return newList2;
}
private List<emp> EmployyeList(List<emp> newList1, List<emp> newList2)
{
var sortedEmpList1 = newList1.OrderBy(i => i.Fname);
var sortedEmpList2 = newList2.OrderBy(i => i.Fname);
List<MeterModel> combinedList = newList1.Union(newList2) as List<emp>;
return combinedList;
}
You can filter the 2nd list to avoid duplicates:
newList1.Union(newList2.Where(emp2 => !newList1.Any(emp1 => emp1.employeeId == emp2.employeeId)))

How to marge child data created by using group by in LINQ?

I've table with following data.
I want to group the data by DocumentID and then want to marge the DocPropIdentifyName and meta value together using comma separator. The output will be like following:
I'm doing it by using a foreach like below:
var test = (from r in lstDocSearch
group r by r.DocumentID
into g
select new
{
DocumentID = g.Key,
MetaValues = g.ToList()
}).ToList();
List<DocSearch> list = new List<DocSearch>();
foreach (var item in test)
{
foreach (var item2 in item.MetaValues)
{
var check = list.Exists(x => x.DocumentID == item2.DocumentID);
if (check)
{
var find = list.FirstOrDefault(x => x.DocumentID == item2.DocumentID);
find.MetaValue = find.MetaValue + ", " + item2.MetaValue;
find.DocPropIdentifyName = find.DocPropIdentifyName + ", " + item2.DocPropIdentifyName;
}
else
{
DocSearch objDocSearch = new DocSearch();
objDocSearch.DocumentID = item2.DocumentID;
objDocSearch.DocPropIdentifyID = item2.DocPropIdentifyID;
objDocSearch.DocPropIdentifyName = item2.DocPropIdentifyName;
objDocSearch.MetaValue = item2.MetaValue;
list.Add(objDocSearch);
}
}
}
But I would like to do this with linq rather than looping through the collection. Is it possible?
Do you mean something like this ? :
var test = (from r in lstDocSearch
group r by r.DocumentID
into g
select new
{
DocumentID = g.Key,
MetaValues = String.Join(",", g.Select(o => o.MetaValue)),
DocPropIdentifyNames = String.Join(",", g.Select(o => o.DocPropIdentifyName)),
}).ToList();

LINQ not sorting List<> properly

My EF query is supposed to be sorting by the date of the first Product in the list, but for some reason, it only sorts most of the products and some of the dates are in the wrong order.
Here's the code...
using (var context = new SalesEntities())
{
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID, c.s84_Customer.CustomerName, c.SubdivisionID, c.s84_Subdivision.SubdivisionName, c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).ToList()
});
var finalList = groupedData.ToList().Where(x => x.Products.Last().Completed == false).ToList();
List<s84_Report_Project_POCO> lst = finalList.OrderBy(x => x.Products.First().ProductDate).ToList();
return lst;
}
Code seems good to me, but look at how one of the dates is out of order...
weird sorting http://www.84sales.com/weird_sort.png
Try doing the order by on the inital select
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID,
c.s84_Customer.CustomerName,
c.SubdivisionID,
c.s84_Subdivision.SubdivisionName,
c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped
.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).OrderBy(x => x.CustomerExpectedDate).ToList()
});
The problem is the .First() function, witch returns the first record, but not necessarly in date order. if you wich to order your grouped datas by date so that the First() function returns the most recent date, you'll need to order your datas before grouping them, and then REorder your results with the First()function :
using (var context = PrimaryConnection.returnNewConnection())
{
var groupedData = context.s84_Schedule.AsExpandable()
.Where(predicate)
.GroupBy(c => new { c.CustomerID, c.s84_Customer.CustomerName, c.SubdivisionID, c.s84_Subdivision.SubdivisionName, c.LotNumber })
.Select(grouped => new s84_Report_Project_POCO
{
CustomerID = grouped.Key.CustomerID,
CustomerName = grouped.Key.CustomerName,
SubdivisionID = grouped.Key.SubdivisionID,
SubdivisionName = grouped.Key.SubdivisionName,
LotNumber = grouped.Key.LotNumber,
Products = grouped
.Select(x => new s84_Report_Project_Product
{
ProductID = x.ProductID,
ProductName = x.s84_Product.ProductName,
ProductDate = x.CustomerExpectedDate,
FieldRepID = x.FieldRepID,
FieldRepName = x.s84_FieldRep.FieldRepName,
InstallerID = x.InstallerID,
InstallerName = x.s84_Installer.InstallerName,
StatusID = x.StatusID,
StatusColor = x.s84_Status.StatusColor,
StatusName = x.s84_Status.StatusName,
Completed = x.Completed
}).Orderby(t => t.CustomerExpectedDate).ToList()
});
var finalList = groupedData.ToList().Where(x => x.Products.Last().Completed == false).ToList();
List<s84_Report_Project_POCO> lst = finalList.OrderBy(x => x.Products.First().ProductDate).ToList();
All SQL queries (and hence Linq queries, when attached to a SQL database) have a random order, unless you sort them.
Products is not sorted - hence it has a random order.
You sort by Products.First(), but Products has a random order, so your sort will also be random.
Make sure Products is sorted within the query, and you should be ok.
Products = grouped.Select(....)
.OrderBy(x => x.ProductDate)
.ToList()

replacement for roundtrip serialize-deserialize

I've a table with over 100 column (including blobs) and I want to make a copy of object only with a few filled columns.
right now I'm doing it by selecting needed columns and doing a round-trip serialize and deserialize with Json.NET which is not efficient. what's the best way to handle this scenario?
BL.Case mCase;
BL.Case temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
mCase = Newtonsoft.Json.JsonConvert.DeserializeObject<BL.Case>(Newtonsoft.Json.JsonConvert.SerializeObject(temp));
Use AutoMapper.
Do something like this:
BL.Case mCase = null;
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
if (temp != null)
{
mCase = Mapper.DynamicMap<BL.Case>(temp);
}
Another solution that requires a bit more code (but might perform better) is to do the following:
In case you need a single item:
BL.Case mCase = null;
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
if (temp != null)
{
mCase = new Case()
{
CaseID = temp.CaseID,
FirstName = temp.FirstName,
LastName = temp.LastName,
};
}
If you need multiple items:
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}); //Here you can filter your query if you want using Where
var result = temp
.ToList() //This will actually execute the query on the database
.Select(x => new Case() //Now you can do this since now we are working on in-memory data
{
CaseID = x.CaseID,
FirstName = x.FirstName,
LastName = x.LastName
});

Categories

Resources