Comparing two lists from different tables with EntityFramework - c#

I want to compare two lists extracted from two different tables
var maListe = db.exclure.Where(w => w.type.Contains("Object class"))
.GroupBy(g => new {libelle = g.libelle,})
.Select(s => new {libellex = s.Key.libelle}).ToList();
var myList = db.Full.Where(c => c.date_reception > new DateTime(2015, 02, 02))
.Where (c => !maListe.Any(c2 => c2.libellex.Contains(c.mc_object_class)))
//.Where (p => p.mc_object_class.CompareTo("NULL")<0)
.GroupBy(f => new
{
object_class = f.mc_object_class,
})
.Select(g => new
{
object_classx = g.Key.object_class,
countx = g.Count()
})
.Take(10)
.OrderByDescending(o => o.countx)
.ToList();
I'm looking for elements that exist in myList and not in maListe, while running the code above I get the following error:
Unable to create a constant value of type 'Anonymous type'. Only
primitive types or enumeration types are supported in this context.'

You should materialize your collection, something like:
var maListe = db.exclure.Where(w => w.type.Contains("Object class"))
.GroupBy(g => new {libelle = g.libelle,})
.Select(s => new {libellex = s.Key.libelle}).ToList();
var myList = db.Full.Where(c => c.date_reception > new DateTime(2015, 02, 02))
.AsEnumerable() // database query ends here
.Where (c => !maListe.Any(c2 => c2.libellex.Contains(c.mc_object_class)))
//.Where (p => p.mc_object_class.CompareTo("NULL")<0)
.GroupBy(f => new
{
object_class = f.mc_object_class,
})
.Select(g => new
{
object_classx = g.Key.object_class,
countx = g.Count()
})
.Take(10)
.OrderByDescending(o => o.countx)
.ToList();
If you will have time, please, take a look to msdn

Related

C# linq select duplicate from an XElement tree

Here is my XElement tree
XElement myShoppingList = new XElement("myShoppingList",
new XElement("Pasadena", new XAttribute("Vendor", "Tesla"),
new XElement("Car",
new XElement("model3",
new XElement("Black")))),
new XElement("LasVegas", new XAttribute("Vendor", "Tesla"),
new XElement("Car",
new XElement("modelY",
new XElement("White")))),
new XElement("Pasadena", new XAttribute("Vendor", "Apple"),
new XElement("Phone",
new XElement("model13",
new XElement("Black")))),
new XElement("Pasadena", new XAttribute("Vendor", "Apple"),
new XElement("Phone",
new XElement("model12",
new XElement("White")))));
I can't seems to get this working, first question - When searching for "Pasadena" I should be getting 3 repeats:
var query = myShoppingList.Elements().AsEnumerable()
.GroupBy(x => x.XPathSelectElement("Pasadena"))
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
When searching for Tesla in LasVegas I'm expecting 1 repeat
var query = myShoppingList.Elements().AsEnumerable()
.GroupBy(x => x.XPathSelectElement("Pasadena[#Name='Tesla']"))
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
And finally I want to search for "White" regardless of who makes the widget then display its maker. So I'm expecting 2 repeats:
var query = myShoppingList.Elements().AsEnumerable()
.GroupBy(x => x.XPathSelectElement("../../../White"))
.Where(g => g.Count() > 1)
.SelectMany(y => y})
.ToList();
I'm not able get this working what am I doing wrong?
I can't seems to get this working, first question - When searching for
"Pasadena" I should be getting 3 repeats:
Is this what you're trying to achieve? :
var query = myShoppingList.XPathSelectElements("Pasadena")
.GroupBy(x => x.Name)
.Select(y => new { Element = y.Key, Counter = y.Count() });
When searching for Tesla in LasVegas I'm expecting 1 repeat
You could try it this way.
var query = myShoppingList.XPathSelectElements("Pasadena")
.Where(x => x.Attributes().Any(x => x.Name == "Vendor" && x.Value == "Tesla"))
.GroupBy(x => x.Name)
.Select(y => new { Element = y.Key, Counter = y.Count() });
For this one i'm not sure if that's what you want to achieve
var query = myShoppingList.XPathSelectElements("//White")
.GroupBy(x => x.Name)
.Select(y => new { Element = y.Key, Counter = y.Count() });

Simplifying a Linq query by using Include instead of Join

I've been asked to simplify the following Linq query:
var orders = db.Orders
.Join(db.Shipments,
o => o.OrderID,
s => s.OrderID,
(o, s) => new { Order = o, Shipment = s })
.Join(db.LineItems,
s => s.Shipment.ShipmentID,
l => l.ShipmentID,
(s, l) => new { Order = s.Order, Shipment = s.Shipment, LineItem = l })
.Join(db.StatusTypes,
s => s.Shipment.StatusTypeID,
st => st.StatusTypeID,
(s, st) => new { Order = s.Order, Shipment = s.Shipment, LineItem = s.LineItem, Description = st.ExternalDescription })
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Order.Created),
OrderNumber = x.Key,
Cost = x.Sum(y => y.LineItem.UnitPrice).ToString(),
Status = x.Max(y => y.Description)
}
);
By replacing the Joins with Includes. I've searched around, and I've discovered that Joins and Includes are somewhat equivalent. But I can't figure out how to convert this query to one that uses includes instead of joins. Is it actually less code and simpler to use includes instead of joins here?
I strongly suggest you to use navigation properties instead of manual builded joins. It will be more efficent and controlable. Read this article.
If you would convert your query to navigation property form by using Include, it would seem like that;
var orders = db.Orders
.Include(x => x.Shipments)
.Include(x => x.Shipments.Select(y => y.LineItems))
.Include(x => x.Shipments.Select(y => y.StatusType))
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Created),
OrderNumber = x.Key,
Cost = x.LineItems.Sum(k => k.UnitPrice),
Status = x.Max(y => y.Description)
}
);
But, as I said, you should define the navigation properties for entities first.
var orders = db.Orders
.Include("Shipments")
.Include("Shipments.LineItems")
.Include("Shipments.StatusTypes")
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Order.Created),
OrderNumber = x.Key,
Cost = x.Sum(y => y.LineItem.UnitPrice).ToString(),
Status = x.Max(y => y.Description)
}
);
i not tested above code ,just try
ObjectQuery.Include Method (String)

Grouping earliest entry for each day using Linq

Trying to get my head around Linq, and at the same time keep track of the time I log on in the morning, which should be the time I get into the office thereabouts.
My code so far is:
EventLog SecurityLog = new EventLog("Security");
var AccountLoggedOnEntries = SecurityLog.Entries.Cast<EventLogEntry>()
.Where(x => x.InstanceId == 4624)
.Select(x => new
{
DateGenerated = x.TimeGenerated.ToShortDateString()
,
TimeGenerated = x.TimeGenerated.ToShortTimeString()
,
x.Message
})
.ToList();
DgvLogSummary.DataSource = AccountLoggedOnEntries;
DgvLogSummary.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
I want to filter the results so that I only have one entry for each day, which is the earliest time.
In SQL I would normally take the Message of the earliest entry and then group by all fields.
How do I perform a similar query in Linq?
In LINQ you would group by, sort each group, and pick the first item:
var AccountLoggedOnEntries = log.Entries.Cast<EventLogEntry>()
.Where(x => x.InstanceId == 4624)
.GroupBy(x => x.TimeGenerated.Date)
.Select(g => g.OrderBy(x => x.TimeGenerated).First())
.Select(x => new {
DateGenerated = x.TimeGenerated.ToShortDateString()
, TimeGenerated = x.TimeGenerated.ToShortTimeString()
, x.Message
})
.ToList();
You could GroupBy the date and then select the minimum time
var AccountLoggedOnEntries = log.Entries.Cast<EventLogEntry>()
.Where(x => x.InstanceId == 4624)
.GroupBy(x => x.TimeGenerated.Date)
.Select(x => new {
DateGenerated = x.Key
, TimeGenerated = x.Min(y => y.TimeGenerated).ToShortTimeString()
})
.ToList();
Getting the appropriate Message is a little more tricky. One easy option is to use x.First().Message in the above Select projection.
Try this :
var AccountLoggedOnEntries = log.Entries.Cast<EventLogEntry>()
.Where(x => x.InstanceId == 4624)
.GroupBy(x => x.TimeGenerated.Date)
.Select(days => days.OrderBy(time => time.TimeGenerated).FirstOrDefault())
.Select(x => new
{
DateGenerated = x.TimeGenerated.ToShortDateString()
,
TimeGenerated = x.TimeGenerated.ToShortTimeString()
,
x.Message
})
.ToList();

Linq GroupBy With Passed Where Predicate

This works fine.g.Key is not null and has appropriate data:
var result = db.JournalEntries.Include(je => je.JournalRecords.Select(jr => jr.Account).Select(j => j.AccountParticulars))
.Where(je => je.Date >= existingLedgerTransaction.From && je.Date <= existingLedgerTransaction.To)
.SelectMany(s => s.JournalRecords)
.GroupBy(d => d.AccountParticular.Account.AccountCategory)
.Select(g => new { Name = g.Key.Name });
But this does not work as g.Key is null:
var DateFilter = new Func<JournalEntry, bool>(je => je.Date >= existingLedgerTransaction.From && je.Date <= existingLedgerTransaction.To);
var result = db.JournalEntries.Include(je => je.JournalRecords.Select(jr => jr.Account).Select(j => j.AccountParticulars))
.Where(DateFilter)
.SelectMany(s => s.JournalRecords)
.GroupBy(d => d.AccountParticular.Account.AccountCategory)
.Select(g => new { Name = g.Key.Name });
I tried the same thing in a simple console app with static collection and passing in predicate works fine. What could be the problem here?
NOTE: Lazy loading/dynamic proxy is disabled
Try
var DateFilter = new Expression<Func<JournalEntry, bool>>(je => je.Date >= existingLedgerTransaction.From && je.Date <= existingLedgerTransaction.To);
as you need to pass an expression tree to EF

LINQ query to dictionary

I'm trying to convert below LINQ query result into dictionary
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Distinct().Count()
});
It gives me a compilation error.
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Distinct().Count()
}).ToDictionary<string, double>(x => x.browser,y=>y.count);
Instance argument: cannot convert from
'System.Linq.IQueryable' to
'System.Linq.ParallelQuery'
got it working.
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Count()
}).ToDictionary(x => x.browser, x => x.count);

Categories

Resources