joining two sets in LINQ - c#

var setsA = new List<SetA> {
new SetA { SsnA = "3450734507", name = "setA"},
new SetA { SsnA = "6833467788", name = "setA"},
new SetA { SsnA = "5452347787", name = "setA"},
new SetA { SsnA = "9345345345", name = "setA"},
};
var setsB = new List<SetB> {
new SetB { SsnB = "5452347787" ,name = "setB"},
new SetB { SsnB = "9345345345", name = "setB"},
};
when i use this linq:
var Set =
from seta in setsA
join setb in setsB
on seta.SsnA
equals setb.SsnB
select new {
SSN = seta.SsnA,
NAME = setb.name
};
i get this value:
{ SSN = "5452347787", NAME = "setB" }
{ SSN = "9345345345", NAME = "setB" }
but i would want to have SET which combines these two and the result would be:
{ SSN = "3450734507", NAME = "setA" }
{ SSN = "6833467788", NAME = "setA" }
{ SSN = "5452347787", NAME = "setB" }
{ SSN = "9345345345", NAME = "setB" }
This would be a result set that would tell me with the name NAME property which set it was taken from, if SSN was found in SetA and SetB it would have property NAME = "setB"
could someone help me with this?

It seems you want an outer join - this is done using GroupJoin:
var set = setsA.GroupJoin(
setsB,
sa => sa.SsnA,
sb => sb.SsnB,
(a, bs) => new { SSN = a.SsnA, NAME = bs.Any() ? "setB" : "setA" });

The LINQ way described here:
http://msdn.microsoft.com/en-us/library/bb397895.aspx would look like this (functionally same to the lambda way):
var set = from a in setsA
join b in setsB on a.SsnA equals b.SsnB into g
from o in g.DefaultIfEmpty()
select new { SSN = a.SsnA, NAME = (o != null ? o.name : a.name)};

Related

C# exclude duplicate code from two method returning expression

I have two functions, returning expression translated to EF.:
public static Expression<Func<TripLanguage, TripViewModel>> ToSearchModel(ILookup<int, TagViewModel> tags)
{
return tripLanguage => new TripViewModel()
{
From = tripLanguage.From,
To = tripLanguage.To,
Annotation = tripLanguage.Description.Truncate(Strings.TRUNCATE_ANOTATION),
Level = tripLanguage.Trip.Level,
BicycleType = tripLanguage.Trip.BicycleType,
UrlId = tripLanguage.UrlId,
Distance = tripLanguage.Trip.Distance,
Tags = tags[tripLanguage.TripId], //This is only different and in function args of course
MainImage = tripLanguage.Trip.Images.OrderBy(s => s.Date).Select(i => new ImageViewModel
{
Filename = i.Filename,
Id = i.Id,
Title = i.Title
}).Take(1)
};
}
public static Expression<Func<TripLanguage, TripViewModel>> ToSearchModel()
{
return tripLanguage => new TripViewModel()
{
From = tripLanguage.From,
To = tripLanguage.To,
Annotation = tripLanguage.Description.Truncate(Strings.TRUNCATE_ANOTATION),
Level = tripLanguage.Trip.Level,
BicycleType = tripLanguage.Trip.BicycleType,
UrlId = tripLanguage.UrlId,
Distance = tripLanguage.Trip.Distance,
MainImage = tripLanguage.Trip.Images.OrderBy(s => s.Date).Select(i => new ImageViewModel
{
Filename = i.Filename,
Id = i.Id,
Title = i.Title
}).Take(1)
};
}
The only different is Tags collection. Is possible something like call method, without arguments and add Tags attribute which exclude duplicate code? Or Use some inheritance expression?
Thank you for your time.
Change the first method to work with null tags, and provide a null default for it:
public static Expression<Func<TripLanguage,TripViewModel>> ToSearchModel(ILookup<int, TagViewModel> tags = null) {
return tripLanguage => new TripViewModel() {
From = tripLanguage.From,
To = tripLanguage.To,
Annotation = tripLanguage.Description.Truncate(Strings.TRUNCATE_ANOTATION),
Level = tripLanguage.Trip.Level,
BicycleType = tripLanguage.Trip.BicycleType,
UrlId = tripLanguage.UrlId,
Distance = tripLanguage.Trip.Distance,
Tags = tags?[tripLanguage.TripId], // <<== Note the question mark
MainImage = tripLanguage.Trip.Images.OrderBy(s => s.Date).Select(i => new ImageViewModel
{
Filename = i.Filename,
Id = i.Id,
Title = i.Title
}).Take(1)
};
}

LAMBDA C# union informations

Using C# with Lambda(or some method), how can I merge different informations(from columns) of the same intituition name ? They can have some common and some different fields.
See a example below:
Have you tried the Group By instruction ?
Here is an other stackoverflow about this : Group by in LINQ
{
List<Instituition> Instituitions = new List<Instituition>() {
new Instituition { Name = "Name1", Alias = "",Area="" },
new Instituition { Name = "Name1", Alias = "Alias1",Area="" },
new Instituition { Name = "name2", Alias = "Audi" ,Area="444"},
new Instituition { Name = "Name1", Alias = "",Area="Garden" }};
var results = Instituitions.GroupBy(i => i.Name,
i => i.Alias,
(key, g) => new
{
Name = key,
Alias = g.Where(a =>a != "").FirstOrDefault(),
Area = Instituitions.Where(a=>a.Name == key && a.Area != "").Select(a=>a.Area).FirstOrDefault()
}
);
}
class Instituition
{
internal string Name;
internal string Alias;
internal string Area;
}

Only one expression can be specified in the select list when the subquery is not introduced with EXISTS

what is the wrong with this LINQ statement:
(from deposit in DAOBase<CashBookDeposit, long>.GetIQueryableBusinessBase()
where deposit.Id == id
select new CashBookDeposit
{
Id = deposit.Id,
DepositeNumber = deposit.DepositeNumber,
DocumentTypeName = deposit.CashBookDepositDocumentType.EnglishName,
StatusName = deposit.CashBookDepositeStatus.EnglishName,
CashbookName = deposit.CashBook.EnglishName,
Collector = deposit.Collector,
Partner = deposit.Partner,
CashBookDepositDocumentType = deposit.CashBookDepositDocumentType,
CreationDate = deposit.CreationDate,
PaidAmount = deposit.TotalAmount,
Description = deposit.Description,
TempReceipts = (from receipt in deposit.TempReceipts
select new TempReceipt
{
Id = receipt.Id,
Code = receipt.Code,
ReceiptNo = receipt.ReceiptNo,
Amount = receipt.Amount,
BusinessPartnerName = receipt.Partner.ENName,
CollectorName = receipt.Collector.EnglishName,
StatusName = receipt.TempReceiptStatus.EnglishName,
CollectionDate = receipt.CollectionDate,
CreationDate = receipt.CreationDate,
Description = receipt.Description,
}).ToList()
}).SingleOrDefault();
i got this exception :
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
need help, thanks
You can change the query as follows:
(from deposit in DAOBase<CashBookDeposit, long>.GetIQueryableBusinessBase()
let receipts = (from tempReceipts in deposit.TempReceipts
select tempReceipts)
where deposit.Id == id
select new CashBookDeposit
{
Id = deposit.Id,
DepositeNumber = deposit.DepositeNumber,
DocumentTypeName = deposit.CashBookDepositDocumentType.EnglishName,
StatusName = deposit.CashBookDepositeStatus.EnglishName,
CashbookName = deposit.CashBook.EnglishName,
Collector = deposit.Collector,
Partner = deposit.Partner,
CashBookDepositDocumentType = deposit.CashBookDepositDocumentType,
CreationDate = deposit.CreationDate,
PaidAmount = deposit.TotalAmount,
Description = deposit.Description,
TempReceipts = (from receipt in receipts
select new TempReceipt
{
Id = receipt.Id,
Code = receipt.Code,
ReceiptNo = receipt.ReceiptNo,
Amount = receipt.Amount,
BusinessPartnerName = receipt.Partner.ENName,
CollectorName = receipt.Collector.EnglishName,
StatusName = receipt.TempReceiptStatus.EnglishName,
CollectionDate = receipt.CollectionDate,
CreationDate = receipt.CreationDate,
Description = receipt.Description,
}).ToList()
}).SingleOrDefault();

How can I access this in C#?

private void LoadSubforums(Forum forum, XElement subforumsXML)
{
forum.Subforums = (from forumItem in subforumsXML.Descendants("forum")
select new Subforum()
{
ID = (string)forumItem.Element("id"),
Name = (string)forumItem.Element("name"),
URL = (string)forumItem.Element("url"),
Description = (string)forumItem.Element("description"),
Type = (string)forumItem.Element("type"),
TopicCount = (string)forumItem.Element("topics"),
ReplyCount = (string)forumItem.Element("replies"),
LastPost = ParseLastPost(forumItem.Element("lastpost")),
IsRedirect = How can I access the LastPost attribute here? :S
}).ToList();
}
}
The IsRedirect attribute of the Subforum class is dependant of a value inside the LastPost attribute.
Is it possible for me to access this attribute from within the Linq query?
EDIT:
This is what I'm trying to do:
forum.Subforums = (from forumItem in subforumsXML.Descendants("forum")
let lastPost = ParseLastPost(forumItem.Element("lastpost"))
select new Subforum()
{
ID = (string)forumItem.Element("id"),
Name = (string)forumItem.Element("name"),
URL = (string)forumItem.Element("url"),
Description = (string)forumItem.Element("description"),
Type = (string)forumItem.Element("type"),
TopicCount = (string)forumItem.Element("topics"),
ReplyCount = (string)forumItem.Element("replies"),
LastPost = lastPost,
IsRedirect = if(lastPost.ID == null) ? true ; false
}).ToList();
But this code doesn't compile.
forum.Subforums = (from forumItem in subforumsXML.Descendants("forum")
let lastPost = ParseLastPost(forumItem.Element("lastpost"))
select new Subforum()
{
ID = (string)forumItem.Element("id"),
Name = (string)forumItem.Element("name"),
URL = (string)forumItem.Element("url"),
Description = (string)forumItem.Element("description"),
Type = (string)forumItem.Element("type"),
TopicCount = (string)forumItem.Element("topics"),
ReplyCount = (string)forumItem.Element("replies"),
LastPost = lastPost,
IsRedirect = !string.IsNullOrEmpty(lastPost)
}).ToList();

IQueryable, converting Anonymous Type to Strong Type

Is there a more elegant/concise way of this; I'd like to get rid of foreach loop with the WorkListItem initialization code.
var queryable = registrations.Select(
r => new
{
r.Id, r.AccountNumber, r.DateAdded, r.DateUpdated, r.Patient, r.Patient.InsuranceInfos
});
var list = queryable.ToList();
var workListItems = new List<WorkListItem>();
foreach (var anonymous in list)
{
var w = new WorkListItem
{
Id = anonymous.Id,
ClientAccountId = anonymous.AccountNumber,
DateAdded = anonymous.DateAdded,
DateUpdated = anonymous.DateUpdated,
Patient = anonymous.Patient,
InsuraceInfos = anonymous.Patient.InsuranceInfos
};
workListItems.Add(w);
}
return workListItems;
Yes you can completely cut out the "middle-man" as it were and select straight into a new WorkListItem as below:
var list = registrations.Select(r => new WorkListItem
{
Id = r.Id,
ClientAccountId = r.AccountNumber,
DateAdded = r.DateAdded,
DateUpdated = r.DateUpdated,
Patient = r.Patient,
InsuraceInfos = r.Patient.InsuranceInfos
}).ToList();

Categories