I have something like this:
And I need to re-write this query into LINQ.
I tried:
var EachProduct = (from b in _context.ReleasePlans
join a in _context.Products
on b.ProductProductId equals a.ProductId
where b.DepartmentDepartmentId == departmentId
select new { ProductId = b, ProductName = a });
But how can I do SUM() and DATEPART() function in Linq?
UPD: Query using lambda expression. But the question remains the same
var EachProduct = _context.ReleasePlans
.Where(b => b.DepartmentDepartmentId == departmentId)
.Join(_context.Products, a => a.ProductProductId, b => b.ProductId,
(b, a) => new {ProductId = b, ProductName = a});
class Program
{
public class ReleasePlan
{
public int ProductProductId { get; set; }
public int Amount { get; set; }
public DateTime DateTime { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int DepartmentDepartmentId { get; set; }
}
static void Main()
{
var products = new List<Product>
{
new Product {ProductId = 1, ProductName = "1", DepartmentDepartmentId = 1},
new Product {ProductId = 2, ProductName = "2", DepartmentDepartmentId = 1},
new Product {ProductId = 3, ProductName = "3", DepartmentDepartmentId = 1},
};
var releasePlans = new List<ReleasePlan>
{
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 1, Amount = 1, DateTime = DateTime.Now.AddMonths(-5)},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 2, Amount = 2, DateTime = DateTime.Now.AddMonths(-5)},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now},
new ReleasePlan {ProductProductId = 3, Amount = 3, DateTime = DateTime.Now.AddMonths(-5)},
};
var amountByProducts = from rp in releasePlans
join p in products
on rp.ProductProductId equals p.ProductId
where p.DepartmentDepartmentId == 1 && (rp.DateTime.AddDays(2).Month/3) == 1
group new {rp, p} by new {rp.ProductProductId, p.ProductId, p.ProductName}
into grp
select new
{
grp.Key.ProductId,
grp.Key.ProductName,
PlannedAmount = grp.Sum(g => g.rp.Amount)
};
Console.WriteLine("ProductId ProductName PlannedAmount");
foreach (var producAmount in amountByProducts)
{
Console.WriteLine("{0} \t\t{1} \t\t{2}", producAmount.ProductId, producAmount.ProductName,
producAmount.PlannedAmount);
}
}
}
Related
There is something that is not working, I cannot figured out...
I want to load data from a List. I have try several codes
MLContext mlContext = new MLContext();
var listData = new List<ProductEntry>
{
new ProductEntry {CoPurchaseProductID = 12, ProductID = 4},
new ProductEntry {CoPurchaseProductID = 12, ProductID = 3},
new ProductEntry {CoPurchaseProductID = 11, ProductID = 5},
new ProductEntry {CoPurchaseProductID = 11, ProductID = 3}
};
var data = mlContext.Data.LoadFromEnumerable(listData);
var options = new MatrixFactorizationTrainer.Options
{
MatrixColumnIndexColumnName = nameof(ProductEntry.ProductID),
MatrixRowIndexColumnName = nameof(ProductEntry.CoPurchaseProductID),
LabelColumnName = "Label",
LossFunction = MatrixFactorizationTrainer.LossFunctionType.SquareLossOneClass,
Alpha = 0.01,
Lambda = 0.025,
Quiet = false,
C = 0.00001,
ApproximationRank = 10,
NumberOfIterations = 20
};
var est = mlContext.Recommendation().Trainers.MatrixFactorization(options);
ITransformer model = est.Fit(data);
var predictionengine = mlContext.Model.CreatePredictionEngine<ProductEntry, Copurchase_prediction>(model);
Console.WriteLine("Calculating the top 3 products for product 3...");
var top5 = (from m in Enumerable.Range(1, 262111)
let p = predictionengine.Predict(
new ProductEntry()
{
ProductID = 3,
CoPurchaseProductID = (uint)m
})
orderby p.Score descending
select (ProductID: m, Score: p.Score)).Take(10);
foreach (var t in top5)
Console.WriteLine($" Score:{t.Score}\tProduct: {t.ProductID}");
Console.ReadKey();
I am getting a problem about a "Label"
This is the classes:
public class Copurchase_prediction
{
public float Score { get; set; }
}
public class ProductEntry
{
[KeyType(count: 262111)]
public float Label { get; set; }
[KeyType(count: 262111)]
public uint ProductID { get; set; }
[KeyType(count: 262111)]
public uint CoPurchaseProductID { get; set; }
}
Getting the error:
System.ArgumentOutOfRangeException: 'Member Label marked with KeyType attribute, but does not appear to be a valid kind of data for a key type (Parameter 'userType')'
Any idea?
Thanks guys!
Remove the [KeyType(count: 262111)] annotation for public float Label { get; set; } property
Label is not a key
I have two tables, Employees and Transactions.
First table: dbo.Employees
Second table: dbo.Transactions
I need to convert the below query to a lambda expression (Linq):
SELECT Employees.EmployeeId, Trans.LastTrans
FROM dbo.Employees
INNER JOIN
(SELECT EmployeeId, MAX(TrasactionDate) LastTrans
FROM dbo.Transactions
GROUP BY EmployeeId) Trans ON Trans.EmployeeId = Employees.EmployeeId
I want the result employeeId and LastTrans as shown below:
See following. The query does not need two Select in linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Context db = new Context()
{
Employees = new List<Employees>() {
new Employees() { EmployeeId = 1, Name = "Hossam"},
new Employees() { EmployeeId = 2, Name = "Peter"},
new Employees() { EmployeeId = 3, Name = "George"}
},
Transactions = new List<Transactions>() {
new Transactions() { TranactionId = 1, amount = 200, TransactionDate = DateTime.Parse("2020-01-02"), EmployeeId = 1},
new Transactions() { TranactionId = 2, amount = 300, TransactionDate = DateTime.Parse("2020-02-02"), EmployeeId = 1},
new Transactions() { TranactionId = 3, amount = 1000, TransactionDate = DateTime.Parse("2020-02-25"), EmployeeId = 1},
new Transactions() { TranactionId = 4, amount = 5000, TransactionDate = DateTime.Parse("2020-04-01"), EmployeeId = 2},
new Transactions() { TranactionId = 5, amount = 7000, TransactionDate = DateTime.Parse("2020-07-16"), EmployeeId = 2},
new Transactions() { TranactionId = 6, amount = 8000, TransactionDate = DateTime.Parse("2020-08-06"), EmployeeId = 3},
new Transactions() { TranactionId = 6, amount = 600, TransactionDate = DateTime.Parse("2020-09-04"), EmployeeId = 3}
}
};
var results = (from trans in db.Transactions
join emp in db.Employees on trans.EmployeeId equals emp.EmployeeId
select new { EmployeeId = trans.EmployeeId, LastTrans = trans.TransactionDate }
).GroupBy(x => x.EmployeeId)
.Select(x => x.OrderByDescending(y => y.LastTrans))
.Select(x => x.First())
.OrderBy(x => x.EmployeeId)
.ToList();
}
}
public class Context
{
public List<Employees> Employees { get; set; }
public List<Transactions> Transactions { get; set; }
}
public class Employees
{
public int EmployeeId { get; set; }
public string Name { get; set; }
}
public class Transactions
{
public int TranactionId { get; set; }
public decimal amount { get; set; }
public DateTime TransactionDate { get; set; }
public int EmployeeId { get; set; }
}
}
This query is enough to get your result and you do not need additional join to Employees
var grouped =
from trans in db.Transactions
group trans by trans.EmployeeId into g
select new
{
EmployeeId = g.Key,
LastTrans = g.Max(x => x.TrasactionDate)
};
I would like to make nested list from this one list
public class Product
{
string Id;
string ProductName;
decimal Price;
string Supplier;
int Quantity;
string VersionId;
string TypeId;
}
public class ProductTypeDto
{
public string TypeId { get; set; }
public string ProductName { get; set; }
public string Price { get; set; }
public List<ProductVersionDto> ProductVersions { get; set; }
}
public class ProductVersionDto
{
public string VersionId { get; set; }
public string ProductName { get; set; }
public string Supplier { get; set; }
public int Quantity { get; set; }
}
I would like to know how I can create a list of ProductTypeDto using linq c# .
I need to get all products with the same TypeId , and ProductVersions field should contain products with same version Id (and of course same TypeId).
I don't want to use foreach loops, and I dont want to loop over products twice to make this nested list.. I think there would be a better way using Linq, would be great if you can help..
Edit: I add here what I have done so far, but it is not the way I want this to be fixed.
List<ProductTypeDto> products = this._dbContext
.Products
.Where(product => product.TypeId == query.TypeId)
.Select(product => new ProductTypeDto()
{
TypeId = product.TypeId,
ProductName = product.ProductName,
Price = product.Price,
ProductVersions = product.Products.Where(p => p.TypeId == product.TypeId)
.Select(p => new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
}).ToList()
})
.ProjectTo<ProductTypeDto>(this._config)
.ToListAsync(cancellationToken);
This is the result I want to get:
var product1 = new Product() { Id = 1, ProductName = "foo", Price = 20, Supplier = "test1", Quantity = 3, VersionId = "1", TypeId = "1" };
var product2 = new Product() { Id = 2, ProductName = "foo1", Price = 60, Supplier = "test2", Quantity = 9, VersionId = "1", TypeId = "1" };
var product3 = new Product() { Id = 3, ProductName = "foo2", Price = 30, Supplier = "test3", Quantity = 5, VersionId = "2", TypeId = "1" };
var product4 = new Product() { Id = 4, ProductName = "foo3", Price = 10, Supplier = "test4", Quantity = 4, VersionId = "1", TypeId = "2" };
var product5 = new Product() { Id = 5, ProductName = "foo4", Price = 50, Supplier = "test5", Quantity = 8, VersionId = "1", TypeId = "3" };
List<ProductVersionDto> p1 = {
new ProductVersionDto { ProductName = "foo", Quantity= 3, Supplier ="test1"}
new ProductVersionDto { ProductName = "foo1", Quantity= 9, Supplier ="test2"}
};
List<ProductVersionDto> p2 = {
new ProductVersionDto { ProductName = "foo3", Quantity= 4, Supplier ="test4"}
};
List<ProductVersionDto> p3 = {
new ProductVersionDto { ProductName = "foo4", Quantity= 8, Supplier ="test5"}
};
List<ProductTypeDto> products = {
new ProductTypeDto{ ProductName = "foo", Price =20, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo1", Price =60, ProductVersions = p1}
new ProductTypeDto{ ProductName = "foo3", Price =10, ProductVersions = p2}
new ProductTypeDto{ ProductName = "foo4", Price =50, ProductVersions = p3}
}
Try this:
var dtos =
(
from p in products
group new ProductVersionDto()
{
VersionId = p.VersionId,
ProductName = p.ProductName,
Supplier = p.Supplier,
Quantity = p.Quantity
} by new { p.TypeId, p.ProductName, p.Price } into g
select new ProductTypeDto()
{
TypeId = g.Key.TypeId,
ProductName = g.Key.TypeId,
Price = g.Key.Price,
ProductVersions = g.ToList(),
}
).ToList();
It appears that you meant Price to be a decimal in ProductTypeDto, BTW.
While working with Linq on Grouping sets, I found a problem while the query is returning the list.
My Code is written in LinqPad
public static void Main()
{
List<RequestEntry> RequestEntries = new List<RequestEntry>(){
new RequestEntry{
RequestId = 1,
RequestedDate = new DateTime(2018, 06, 01),
ApproverUserId = "STEVES",
ApproverUserName = "Steve Smith",
AuthorizerUserId = "JAMESS",
AuthorizerUserName = "James Sutherland"
},
new RequestEntry{
RequestId = 1,
RequestedDate = new DateTime(2018, 06, 01),
ApproverUserId = "GRAHAMS",
ApproverUserName = "Graham Smith",
AuthorizerUserId = "THABANGM",
AuthorizerUserName = "Thabang Moroe"
},
new RequestEntry{
RequestId = 2,
RequestedDate = new DateTime(2018, 06, 02),
ApproverUserId = "STEVES",
ApproverUserName = "Steve Smith",
AuthorizerUserId = "JAMESS",
AuthorizerUserName = "James Sutherland"
},
new RequestEntry{
RequestId = 3,
RequestedDate = new DateTime(2018, 06, 03),
ApproverUserId = "ROBINS",
ApproverUserName = "Robin Smith",
AuthorizerUserId = "TOMH",
AuthorizerUserName = "Tom Harrision"
},
new RequestEntry{
RequestId = 3,
RequestedDate = new DateTime(2018, 06, 03),
ApproverUserId = "CHRISS",
ApproverUserName = "Chris Smith",
AuthorizerUserId = "TOMH",
AuthorizerUserName = "Tom Harrision"
},
new RequestEntry{
RequestId = 3,
RequestedDate = new DateTime(2018, 06, 03),
ApproverUserId = "LIAMS",
ApproverUserName = "Liam Smith",
AuthorizerUserId = "TOMH",
AuthorizerUserName = "Tom Harrision"
}
};
var results = (
from r in RequestEntries
group r by new
{
r.RequestId, r.RequestedDate
} into g
select new RequestWithApprover(){
RequestId = g.Key.RequestId,
RequestedDate = g.Key.RequestedDate,
ApproverUserIds = g.Select(c => c.ApproverUserId).ToList(),
RequestApprovers = g.Select(c => new RequestApprover(){
ApproverUserName = c.ApproverUserName,
ApproverUserId = c.ApproverUserId
}).ToList(),
RequestAuthorizers = g.Select(c => new RequestAuthorizer(){
AuthorizerUserName = c.AuthorizerUserName,
AuthorizerUserId = c.AuthorizerUserId
}).ToList()
}).ToList();
results.Dump();
}
public class RequestEntry
{
public int RequestId
{
get;
set;
}
public string ApproverUserId
{
get;
set;
}
public string ApproverUserName
{
get;
set;
}
public string AuthorizerUserId
{
get;
set;
}
public string AuthorizerUserName
{
get;
set;
}
public DateTime RequestedDate
{
get;
set;
}
}
public class RequestApprover
{
public string ApproverUserId
{
get;
set;
}
public string ApproverUserName
{
get;
set;
}
}
public class RequestAuthorizer
{
public string AuthorizerUserId
{
get;
set;
}
public string AuthorizerUserName
{
get;
set;
}
}
public class RequestWithApprover
{
public int RequestId
{
get;
set;
}
public DateTime RequestedDate
{
get;
set;
}
public List<string> ApproverUserIds
{
get;
set;
}
public List<RequestApprover> RequestApprovers
{
get;
set;
}
public List<RequestAuthorizer> RequestAuthorizers
{
get;
set;
}
}
What I found is, For RequestID =3, the Number of RequestAuthorizer items should be 1, but it had multiplied. I found that in RequestID =3 the Maximum items in any list is 3, the RequestAuthorizer to multiplies to that Number. Refer below snapshot highlighted of the result:
Technically, In RequestId=3 the List<RequestAuthorizer> should only contain the Item of Tom Harrision and the count should be one.
How could I correct it?
How about grouping the RequestAuthorizer?
var results = (
from r in RequestEntries
group r by new
{
r.RequestId, r.RequestedDate
} into g
select new RequestWithApprover(){
RequestId = g.Key.RequestId,
RequestedDate = g.Key.RequestedDate,
ApproverUserIds = g.Select(c => c.ApproverUserId).ToList(),
RequestApprovers = g.Select(c => new RequestApprover(){
ApproverUserName = c.ApproverUserName,
ApproverUserId = c.ApproverUserId
}).ToList(),
RequestAuthorizers = g.
GroupBy(g1 => new {
g1.AuthorizerUserName,
g1.AuthorizerUserId }).
Select(c => new RequestAuthorizer(){
AuthorizerUserName = c.Key.AuthorizerUserName,
AuthorizerUserId = c.Key.AuthorizerUserId
}).ToList()
}).ToList();
I have an entity list, where one of the fields (UtcOffset) is a number.
And I have a filter list offsets which is a list of numbers.
I want to select with a LINQ from the first list all the entities where the UtcOffset field is equal or less than to the values from the filter list with the fixed delta (3600) added.
I have a code that works for "equal-case" only
public class TimeZone
{
public int Id { get; set; }
public string Name { get; set; }
public int UtcOffset { get; set; }
}
var delta = 3600;
List<TimeZone> TimeZones = new List<TimeZone>()
{
new TimeZone() {Id = 1, Name = "America/Tortola", UtcOffset = -14400},
new TimeZone() {Id = 2, Name = "Asia/Kathmandu", UtcOffset = 20700},
new TimeZone() {Id = 3, Name = "Asia/Kolkata", UtcOffset = 19800},
new TimeZone() {Id = 4, Name = "Africa/Tunis", UtcOffset = 3600},
new TimeZone() {Id = 5, Name = "Africa/Windhoek", UtcOffset = 7200},
new TimeZone() {Id = 6, Name = "Europe/Simferopol", UtcOffset = 10800},
}
List<Int32> offsets = new List<Int32>()
{
3600, -10800, -14400
};
var matchedList = TimeZones.Where(t => offsets.Contains(t.UtcOffset)).ToList();
It returns entities with ids 1 and 4.
I want to select entities with ids 1, 4, 5 (which have UtcOffset less or equal than 3600 + delta, -10800 + delta, -14400 + delta).
How I can modify my LINQ expression to match this case?
If you want it to work more efficiently, just use this (credits to #yawnobleix for spotting this, though it really needs to be Max() not Min()):
var matchedList = TimeZones.Where(t => t.UtcOffset <= (offsets.Max() + delta)).ToList();
This way:
class Program
{
static void Main(string[] args)
{
var delta = 3600;
List<TimeZone> TimeZones = new List<TimeZone>()
{
new TimeZone() {Id = 1, Name = "America/Tortola", UtcOffset = -14400},
new TimeZone() {Id = 2, Name = "Asia/Kathmandu", UtcOffset = 20700},
new TimeZone() {Id = 3, Name = "Asia/Kolkata", UtcOffset = 19800},
new TimeZone() {Id = 4, Name = "Africa/Tunis", UtcOffset = 3600},
new TimeZone() {Id = 5, Name = "Africa/Windhoek", UtcOffset = 7200},
new TimeZone() {Id = 6, Name = "Europe/Simferopol", UtcOffset = 10800},
};
List<Int32> offsets = new List<Int32>()
{
3600, -10800, -14400
};
var matchedList = TimeZones.Where(x => offsets.Any(y => x.UtcOffset <= (y + delta))).ToList();
}
}
public class TimeZone
{
public int Id { get; set; }
public string Name { get; set; }
public int UtcOffset { get; set; }
}