Linq order by column, give priority to column with value - linq

I have 3 tables,
Table Operation
Columns:
idOperation int cdLangPrimary char(2)
Table Languages
Columns:
cdLang char(2) nmLang nvarchar(10)
Table OperationLanguages
Columns: idOperation int cdLang char(2)
My code:
var jsonObject = dbContext.Operations
.Single(o => o.idOperation == idOperation)
.Languages
.Select(l => new { l.cdLang, l.nmLang });
What I was trying to do (with no success),
is Order the Languages by a-Z, but put the cdLangPrimary as the first.
I know it is possible if I create a List(or Dictionary) like so:
var languages = new List<Languages>();
var dLanguage = operation.Languages.Single(l => l.cdLang == operation.cdLangPRIMARY);
languages.Add(dLanguage);
languages.AddRange(operation.Languages.Where(l => l.cdLang != dLanguage.cdLang));
Just wondering if there is an option to the same with linq
or in a more effective way?

If I understand your question, the following should do it:
var result = dbContext.Languages
.Where(l => l.OperationId == idOperation)
.OrderByDescending(l => l.cdLang == l.Operation.cdLangPrimary)
.ThenBy(l => l.cdLang)
.Select(l => new { l.cdLang, l.nmLang });
If you don't have relationships set up in entity framework between an Operation and a Language then you can achieve the same result as follows:
var operation = dbContext.Operations
.SingleOrDefault(o => o.idOperation == idOperation);
if(operation != null)
{
var result = dbContext.Languages
.Where(l => l.OperationId == idOperation)
.OrderByDescending(l => l.cdLang == operation.cdLangPrimary)
.ThenBy(l => l.cdLang)
.Select(l => new { l.cdLang, l.nmLang });
}

Related

How to do a cascading IGrouping?

I'm trying to do a cascading groupby, but I can't find a way to get the proper index in the end (the .ElementAt(0) in the end of the code is wrong, in all 3 levels of hierarchy).
//Level
//---|Category
//---|---|Family
//---|---|---|Type
//---|---|---|---|Leaf
var leafs = queryLeafs.ToList();
foreach (var leaf in leafs)
{
//Get Type
var leafAttr = leaf.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long typeId = leafAttr.Value.Value;
leaf.Type = universe.First(o => o.Id == typeId);
//Family
var typeAttr = leaf.Type.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long familyId = typeAttr.Value.Value;
leaf.Family = universe.First(o => o.Id == familyId);
//Category
var familyAttr = leaf.Family.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long categoryId = familyAttr.Value.Value;
leaf.Category = universe.First(o => o.Id == categoryId);
}
var groupType = leafs.GroupBy(leaf => leaf.Type);
var groupFamily = groupType.GroupBy(t => **t.ElementAt(0)**.Family);
var groupCategory = groupFamily.GroupBy(f => **f.ElementAt(0).ElementAt(0)**.Category);
Can someone provide a light in my dark path?
If you have any suggestion on how to improve this question, I would appreciate with all my heart.

AngleSharp - Find innermost nested tables

I try to get a list of all innermost tables with AngleSharp. This tables doesn't contain any tables.
With HtmlAgilityPack I've realised it this way:
var wrapper = html.DocumentNode.SelectSingleNode(".//td[#class='wrapper']");
var innerMostTables = wrapper.SelectNodes(".//table [not(descendant::table)]");
With AngleSharp I've tried this, but it doesn't work:
var parser = new HtmlParser();
var document = parser.Parse(html);
var wrapper = document.All.Where(d => d.ClassName == "wrapper");
var innerMostTables = wrapper.Where(w => w.Descendents()
.Select(c => c.NodeName == "table").Count() == 0);
I could solve the problem:
foreach (IElement ch in wrapper.Descendents()
.Where(d => d.NodeName == "TABLE" && d.Descendents()
.Where(d2 => d2.NodeName == "TABLE").Count() == 0))
{
Console.WriteLine(ch.OuterHtml);
}

Cannot convert from IEnumerable<List> to List

I am working on these lists to get an item that matches the selected item from the combobox.
private void InitializaMessageElement()
{
if (_selectedTransactionWsName != null)
{
get a transaction webservice name matching the selected item from the drop down here the output=TestWS which is correct
var getTranTypeWsName = TransactionTypeVModel
.GetAllTransactionTypes()
.FirstOrDefault(transTypes =>
transTypes.WsMethodName == _selectedTransactionWsName);
Loop the list of wsnames from the treenode list. Here it gives me all the node I have which is correct.
var wsNameList = MessageElementVModel
.GetAllTreeNodes().Select(ame =>
ame.Children).ToList();//. == getTranTypeWsName.WsMethodName);
find the getTranTypeWsName.WsMethodName in the wsNameList. Here is where I have the problem:
var msgElementList = MessageElementVModel.GetAllTreeNodes()
.Select(ame => ame.Children).Where(c =>
{
c.Where(d => getTranTypeWsName != null && d.Name == getTranTypeWsName.WsMethodName);
return false;
});
my MsgElement list:
var _msgElementList = new ObservableCollection<MessageElementViewModel>(msgElementList);
this.messageElements = _msgElementList;
NotifyPropertyChanged("MessageElements");
}
Here it is returning wrong data. It returns all the list I have a non filtered one.
Why is my out put inconsistent? I am new to LINQ.
This part of your code seems problematic:
var msgElementList = wsNameList.SingleOrDefault(x =>
{
x.Where(ame => ame.Name == getTranTypeWsName.WsMethodName);
return true;
});
You were expecting a list but you used the SingleOrDefault(), which is meant to be used in retrieving a single record.
Try this, which will retrieve msgElementList. No need to get all tree nodes first and store it in wsNameList:
// Assumed that Name is a property of Children
var msgElementList = MessageElementVModel.GetAllTreeNodes()
.Select(ame => ame.Children).Where(c => c.Name == getTranTypeWsName.WsMethodName).ToList();
Here is a solution:
var msgElementList = wsNameList.SelectMany(x => x.Where(ame => getTranTypeWsName != null && ame.Name == getTranTypeWsName.WsMethodName)).ToList();

Dynamic Where clauses with multiple joins using Linq

I need to build a dynamic where clause in a Linq statement with multiple joins.
.Net 3.5
Linq-To-Sql
I have these incoming parameters for the Linq statement, only the "UID" is required.
int uid = 23702; // <-- Only one Required
string courseNumber = "";
string title = "";
int? categoryId = null;
int? typeId = null;
I've been testing this out in LinqPad and while I've gotten the query to work with all Where clauses in place, the Nullable int parameters end up returning incorrect results.
Here's my Linq statement:
var ci = course_instances;
var query = courses.Join(ci,
c => c.course_id,
i => i.course_id,
(c, i) => new
{
c = c,
i = i
}).Join(user_courses,
temp => temp.i.instance_id,
uc => uc.instance_id,
(temp, uc) => new
{
temp = temp,
uc = uc
})
.Where (temp1 => (temp1.uc.uid == uid))
.Where (temp1 => (temp1.temp.c.course_number.Contains(courseNumber)))
.Where (temp1 => (temp1.temp.c.title.Contains(title)))
//.Where (temp1 => (temp1.temp.c.course_type_id == typeId))
//.Where (temp1 => (temp1.temp.c.course_category_id == categoryId))
.Select (temp1 => new CourseSearchMyCourses
{
// snipped the many properties
});
I've tried using PredicateBuilder, but it returns the error:
The type arguments for method 'System.Linq.Queryable.Where(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Here's my PredicateBuilder Linq attempt:
var conditions = PredicateBuilder.True<user_course>();
conditions = conditions.And(c => c.uid == uid);
var ci = course_instances;
var query = courses.Join(ci,
c => c.course_id,
i => i.course_id,
(c, i) => new
{
c = c,
i = i
}).Join(user_courses,
temp => temp.i.instance_id,
uc => uc.instance_id,
(temp, uc) => new
{
temp = temp,
uc = uc
})
.Where (conditions)
.Select (temp1 => new CourseSearchMyCourses
{
// snipped the many properties
});
BTW, I also tried using "System.Linq.Dynamic" using string queries, and got the error the " and " isn't recognized.
Any help is appreciated.
Thanks.
Linq predicates with nullable type variables get translated into a SQL predicate = NULL. But that is totally different than what it should be: IS NULL.
You expect to get the rows where course_type_id is empty, but the = comparison returns no results because NULL is not a value and the comparison returns UNKNOWN. I think that is the cause of your "incorrect results".
If this is your problem, a fix can be found here.

LINQ: Group By + Where in clause

I'm trying to implement a T-SQL equivalent of a where in (select ...) code in LINQ.
This is what I have now:
int contactID = GetContactID();
IEnumerable<string> threadList = (from s in pdc.Messages
where s.ContactID == contactID
group 1 by new { s.ThreadID } into d
select new { ThreadID = d.Key.ThreadID}).ToList<string>();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group new { s } by new { s.ThreadID } into d
let maxMsgID = d.Where(x => x.s.ContactID != contactID).Max(x => x.s.MessageID)
select new {
LastMessage = d.Where(x => x.s.MessageID == maxMsgID).SingleOrDefault().s
};
However, my code won't compile due to this error for the ToList():
cannot convert from
'System.Linq.IQueryable<AnonymousType#1>'
to
'System.Collections.Generic.IEnumerable<string>'
Anyone have any suggestions on how to implement this? Or any suggestions on how to simplify this code?
Your query returns a set of anonymous types; you cannot implicitly convert it to a List<string>.
Instead, you should select the string itself. You don't need any anonymous types.
Change it to
var threadList = pdc.Messages.Where(s => s.ContactID == contactID)
.Select(s => s.ThreadID)
.Distinct()
.ToList();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group s by s.ThreadID into d
let maxMsgID = d.Where(x => x.ContactID != contactID).Max(x => x.MessageID)
select new {
LastMessage = d.Where(x => x.MessageID == maxMsgID).SingleOrDefault()
};

Resources