How convert to linq request? - c#

var list = new List<ListCreaditInBankView>();
var banktemp = m_banksRepository.Banks;
foreach (Bank bank in banktemp)
{
var bankbranchtemp = m_banksRepository.BankBranches.Where(x => x.BankId == bank.Id);
foreach (BankBranch bankBranch in bankbranchtemp)
{
var creditortemp = m_creditorsRepository.Creditors.Where(x => x.BankBranchId == bankBranch.Id);
list.Add(new ListCreaditInBankView(){Bank = bank, Creditors = creditortemp});
}
}
I need get List<ListCreaditInBankView> without these cycles.
I tried, but it only gets a Creditors
var lists = (from bank in banksTemp
let creditorBank = m_creditorsRepository.GetCreditorBank(bank.BankBranches.Select(x => x.Id).ToList())
select new ListCreaditInBankView() {Bank = bank, Creditors = creditorBank}).ToList();

Try the following:
var lists = (from bank in m_banksRepository.Banks
select new ListCreaditInBankView
{
Bank = bank,
Creditors = creditorsRepository.GetCreditorBank(bank.BankBranches
.Select(x => x.Id).ToList())
}).ToList();
Or if you prefer the other style LINQ (method chaining it's called, thanks Numan :)):
var lists = m_banksRepository.Banks
.Select(bank => new ListCreaditInBankView
{
Bank = bank,
Creditors = creditorsRepository.GetCreditorBank(bank.BankBranches
.Select(x => x.Id).ToList())
}).ToList();

If you're using Linq 2 Entity framework, there's another approach you can try.
http://msdn.microsoft.com/en-us/library/bb896272.aspx
You just need to be sure, that you've set your tables and keys in your database correctly (or at least mapping in the generated model), otherwise it won't work.

Related

Call Function In LinQ Query

I want to sum price for all products that is in list.
I called a funtion in linQ query.
Total = t0.TbOfferProducts.Sum(x => Customs.CalculateCurrency(x.TbOffer.Price))
But it didnt recognize my function
I wrote another function for linQ, then I called it. But linQ dont recognize my function.
Error:
LINQ to Entities does not recognize the method 'Double Cal_Price(Int32)' method, and this method cannot be translated into a store expression.
I try other versions but none of them didnt work.Help me please.
myList =
(from t0 in DB.TbProducts
where t0.BoActive == true && t0.BoSoftDeleted == false
let price = Cal_Price(t0.InProductId)
select new ProductActivityInfo
{
ID = t0.InProductId,
Name = t0.StProductName,
Code = t0.StProductCode,
Total = price
})
public double Cal_Price(int productId)
{
double total = 0;
using (MyEntityContext DB = new MyEntityContext())
{
var list = DB.TbOfferProducts.Where(x => x.InProductId == productId);
foreach (var item in list)
{
total += Customs.CalculateCurrency(item.TbOffer.Price);
}
}
return total;
}
EF Core is tryng to build SQL but fails when found custom compiled method in query. Correct Total on the client side:
// calculate sum by grouping
var offerPrices =
from op in DB.TbOfferProducts
group op.TbOffer.Price by x.InProductId
select new
{
ProductId = g.Key,
RawPrice = g.Sum()
};
var result =
(from t0 in DB.TbProducts
join op in offerPrices on t0.InProductId equals op.ProductId
where t0.BoActive == true && t0.BoSoftDeleted == false
select new ProductActivityInfo
{
ID = t0.InProductId,
Name = t0.StProductName,
Code = t0.StProductCode,
Total = op.RawPrice
})
.ToList();
// correct Total on the client side
result.ForEach(x => x.Total = Customs.CalculateCurrency(x.Total));

Linq query optimization/summarize

I have the following query:
var countA=await _importContext.table1.CountAsync(ssc => ssc.ImportId == importId)
var countB=await _importContext.table2.CountAsync(ssc => ssc.ImportId == importId)
var countC=await _importContext.table3.CountAsync(ssc => ssc.ImportId == importId)
var countD=await _importContext.table4.CountAsync(ssc => ssc.ImportId == importId)
There are 9 more count from different tables. Is there a way to summarize the query in terms of optimizing & removing redundancy?
I tried wrapping up the queries like:
var result = new
{
countA = context.table1.Count(),
countB = context.table2.Count(),
.....
};
but this takes more time than the first one above.
You can't really optimise it as you seem to need the counts from all of the tables. Your second method of getting the data still calls the database the same amount of times as the first but also creates an object containing all of the counts so is likely to take longer.
The only thing you can really do to make it faster is to get the data in parallel but this might be overkill. I would just go with your first option unless it's really slow.
You can create such query via gouping by constant and Concat operator:
Helper class:
public class TableResult
{
public string Name { get; set; }
public int Count { get; set; }
}
Query:
var query = _importContext.table1.Where(ssc.ImportId == importId).GroupBy(x => 1).Select(g => new TableResult { Name = "table1", Count = g.Count() })
.Concat(_importContext.table2.Where(ssc.ImportId == importId).GroupBy(x => 1).Select(g => new TableResult { Name = "table2", Count = g.Count() }))
.Concat(_importContext.table3.Where(ssc.ImportId == importId).GroupBy(x => 1).Select(g => new TableResult { Name = "table3", Count = g.Count() }))
.Concat(_importContext.table4.Where(ssc.ImportId == importId).GroupBy(x => 1).Select(g => new TableResult { Name = "table4", Count = g.Count() }));
var result = await query.ToListAsync();

display two table data at a time in linq

I want to to display two tables information at a time.
List<int> order_track = db.Order_Trackings.Where(e => e.UID == id).Select(q => q.ID).ToList();
if (order_track == null)
{
var rate = db.Ratings.OrderByDescending(e => e.Rate).Take(5);
}
List<int> fidList = db.OrderFoods.Where(q => order_track.Contains(q.OID)).Select(q => q.FID).ToList();
var qs = (from x in fidList
group x by x into g
let count = g.Count()
orderby count descending
select new { KEY = g.Key });
if (order_track.Count == 2)
{
var one = qs;
List<int> idList = new List<int>();
foreach (var val in one)
{
idList.Add(val.KEY);
}
var food = db.Foods.Where(q => idList.Contains(q.ID));
var rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault();
return Request.CreateResponse(HttpStatusCode.OK, rate);
I want to do something like this I hope you will understand what i am trying to achieve Thanks in advance.
var food = db.Foods.Where(q => idList.Contains(q.ID)&&db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault());
return Request.CreateResponse(HttpStatusCode.OK, rate);
If you want to combine the two results into one variable, then the easiest way to do so is by creating an anonymous object, like this:
var result = new
{
food = db.Foods.Where(q => idList.Contains(q.ID)),
rate = db.Ratings.OrderByDescending(e => e.Rate).FirstorDefault()
};
return Request.CreateResponse(HttpStatusCode.OK, result);
You could also create a class with two properties and then create an instance of that class, but if this is the only place where you would use that class then I wouldn't bother doing that.

Unable to get a distinct list that contains summed values

I have posted this earlier but the objective of what I am trying to achieve seems to have lost hence re-posting it to get explain myself better.
I have a collection that has duplicate productnames with different values. My aim is to get a list that would sum these productnames so that the list contains single record of these duplicates.
For e.g
If the list contains
Product A 100
Product A 200
The result object should contain
Product A 300
So as you can see in my code below, I am passing IEnumerable allocationsGrouped to the method. I am grouping by productname and summing the Emv fields and then looping it so that I created a new list of the type List and pass it to the caller method. The problem what I seeing here is on the following line of code Items = group. Items now contains original list without the sum. Hence the inner foreach loop runs more than ones because there are duplicates which defeats my purpose. I finally need to return result object that has non duplicate values which are summed based on the above criteria. Could you please tell me where I am going wrong.
private static List<FirmWideAllocationsViewModel> CreateHierarchy(string manStratName, IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> allocationsGrouped, List<FirmWideAllocationsViewModel> result)
{
var a = allocationsGrouped
.Where(product => !string.IsNullOrEmpty(product.PRODUCT_NAME))
.GroupBy(product => product.PRODUCT_NAME)
.Select(group => new
{
ProductName = group.Key, // this is the value you grouped on - the ProductName
EmvSum = group.Sum(x => x.EMV),
Items = group
});
var b = a;
var item = new FirmWideAllocationsViewModel();
item.Hierarchy = new List<string>();
item.Hierarchy.Add(manStratName);
result.Add(item);
foreach (var ac in b)
{
var productName = ac.ProductName;
var emvSum = ac.EmvSum;
foreach (var elem in ac.Items)
{
var item2 = new FirmWideAllocationsViewModel();
item2.Hierarchy = new List<string>();
item2.Hierarchy.Add(manStratName);
item2.Hierarchy.Add(elem.PRODUCT_NAME);
item2.FirmID = elem.FIRM_ID;
item2.FirmName = elem.FIRM_NAME;
item2.ManagerStrategyID = elem.MANAGER_STRATEGY_ID;
item2.ManagerStrategyName = elem.MANAGER_STRATEGY_NAME;
item2.ManagerAccountClassID = elem.MANAGER_ACCOUNTING_CLASS_ID;
item2.ManagerAccountingClassName = elem.MANAGER_ACCOUNTING_CLASS_NAME;
item2.ManagerFundID = elem.MANAGER_FUND_ID;
item2.ManagerFundName = elem.MANAGER_FUND_NAME;
item2.Nav = elem.NAV;
item2.EvalDate = elem.EVAL_DATE.HasValue ? elem.EVAL_DATE.Value.ToString("MMM dd, yyyy") : string.Empty;
item2.ProductID = elem.PRODUCT_ID;
item2.ProductName = elem.PRODUCT_NAME;
item2.UsdEmv = Math.Round((decimal)elem.UsdEmv);
item2.GroupPercent = elem.GroupPercent;
item2.WeightWithEq = elem.WEIGHT_WITH_EQ;
result.Add(item2);
}
}
return result;
}
change it to:
var result = allocationsGrouped
.Where(product => !string.IsNullOrEmpty(product.PRODUCT_NAME))
.GroupBy(product => product.PRODUCT_NAME)
.Select(group => {
var product = group.First();
return new FirmWideAllocationsViewModel()
{
Hierarchy = new List<string>() { manStratName, product.PRODUCT_NAME },
FirmID = product.FIRM_ID,
FirmName = product.Item.FIRM_NAME,
ManagerStrategyID = product.MANAGER_STRATEGY_ID,
ManagerStrategyName = product.MANAGER_STRATEGY_NAME,
ManagerAccountClassID = product.MANAGER_ACCOUNTING_CLASS_ID,
ManagerAccountingClassName = product.MANAGER_ACCOUNTING_CLASS_NAME,
ManagerFundID = product.MANAGER_FUND_ID,
ManagerFundName = product.MANAGER_FUND_NAME,
Nav = product.NAV,
EvalDate = product.EVAL_DATE.HasValue ? product.EVAL_DATE.Value.ToString("MMM dd, yyyy") : string.Empty,
ProductID = product.PRODUCT_ID,
ProductName = product.PRODUCT_NAME,
UsdEmv = Math.Round((decimal)product.UsdEmv),
GroupPercent = product.GroupPercent,
WeightWithEq = product.WEIGHT_WITH_EQ,
//assign aggregate Sum here
EmvSum = group.Sum(x => x.EMV),
};
});

Filter and add values using C# using lambda expression

New to C# and appreciate any help. The issue is that I need to filter the results of my api call against an array (using an "allowedA" and "allowedB" array.) I don't know how to edit the lambda expression to check against the loop.
var activities = await _restClientTaxonomy.GetTaxonomyFullAsync(TAXONOMY_CLASSIFICATIONID_FOR_ACTIVITY);
var activityTypes = await _restClientTaxonomy.GetTaxonomyFullAsync(TAXONOMY_CLASSIFICATIONID_FOR_ACTIVITY_TYPES);
var documentEventxx = activities.Select(type => type.Id);
long [] allowedA = new long []{ 7137, 40385637};
long [] allowedB = new long []{ 7137, 40385637};
foreach (long value in documentEventxx)
{
foreach (var item in allowed)
{
if (item == value) {
//These are the values I am looking for -> values that are part of the documentEventxx and allowedB.
}
}
}
var result = activityTypes.Select(type => new CategoryViewModel
{
Id = type.Id,//This is where I want to add only items that are in the allowedA array
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id, //This is where I want to add only items that are in the allowedB array
Text = t.Name
}).ToList()
}).ToArray();
I have been reading about lambda expressions and foreach loops so please don't just post a random link.
Thanks in advance.
Filter the values before Selecting.
activityTypes.Where(x=>allowedA.Contains(x.Id)).Select(type => new CategoryViewModel
{
Id = type.Id,
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id && allowedB.Contains(a.Id)).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id,
Text = t.Name
}).ToList()
})
To filter you use .Where. You .Select to create a list of new types. So in order to filter, then create the lists of objects you want:
var result = activityTypes.Where(type=>isAllowed(type.Id)).Select(type => new CategoryViewModel
{
Id = type.Id,//This is where I want to add only items that are in the allowedA array
Text = type.Name,
Types = activities.Where(a => a.ParentId == type.Id&&isAllowed(a.Id)).Select(t => new TaxonomyMemberTextItem
{
Id = t.Id, //This is where I want to add only items that are in the allowedB array
Text = t.Name
}).ToList()
}).ToArray();

Categories