Lambda Expression for Finding properties - c#

I want to retreive LineOfBusiness property from promotionCatalogResponseRootObject where PromotionID is equal to myId
public class PromotionCatalogResponseRootObject
{
public PromotionCatalogResponse PromotionCatalog { get; set; }
}
public class Promotion
{
public string PromotionId { get; set; }
public string LineOfBusiness { get; set; }
public string PromotionName { get; set; }
}
public class PromotionCatalogResponse
{
public List<Promotion> Promotion { get; set; }
}
I started off like this but I know I'm doing it wrong. Please guide
string myId = "7596";
string lineOfBusiness = dataPromotionCatalog.PromotionCatalog
.Promotion.Find(p => p.LineOfBusiness);

What you are missing is the the Find method is expecting to receive a predicate with a bool return value but you are returning a string, the LineOfBusiness property.
First filter the items you want and then select the desired property. In addition, I'd go with the Where instead of the Find. (Find() vs. Where().FirstOrDefault())
var result = dataPromotionCatalog.PromotionCatalog.Promotion
.Where(i => i.PromotionId == myId)
.Select(i => i.LineOfBusiness);
or in query syntax
var result = (from item in dataPromotionCatalog.PromotionCatalog.Promotion
where item.PromotionId == myId
select item.LineOfBusiness);
If you are expecting/want to have one item then use FirstOrDefault:
var result = dataPromotionCatalog.PromotionCatalog.Promotion
.FirstOrDefault(i => i.PromotionId == myId)?.LineOfBusiness;

Related

Count the number of element present in the inner list

public Class Users
{
string UserName,
List<UserDesktop> userDesktop
}
public class UserDesktop
{
int ID,
string DesktopName,
string type -- here Type value is A, B;
}
Here I have to find the users count having desktop assigned of type A
Users variable containing all data.
List<Users> finalUsers = users.Count(s=>s.userDesktop.where(x=>x.type == "A"))
Please let me know the correct way of doing it.
You might want to use SelectMany to flatten the list then count it:
int numberOfUsersWithDesktopOfTypeA = users.SelectMany(u => u.userDesktop)
.Count(ud => ud.type == "A");
If you want the list of users that have an A desktop:
var usersWithDesktopA = Users.Where(u => u.Any(ud => ud.type == "A"));
var numberOfUsersWithDesktopA = usersWithDesktopA.Count();
To query the user(s) who has UserDesktop of type 'A':
List<Users> hasDesktopAUsers = users.Where(u => u.userDesktop.Any(ud => ud.type == "A"))
.ToList();
Next, you can get the number of count from the previous result as:
int numberOfDesktopAUsers = hasDesktopAUsers.Count;
Out of topic:
It is recommended to have a proper naming convention for handling single and plural terms to avoid confusion. For example:
public class User
{
public string UserName { get; set; }
public List<UserDesktop> UserDesktops { get; set; }
}
public class UserDesktop
{
public int ID { get; set; }
public string DesktopName { get; set; }
public string Type { get; set; }
}
From the above, you should name as User as it is an User object while UserDesktops with 's' as it is a collection set.
Final solution:
List<User> hasDesktopAUsers = users.Where(u => u.UserDesktops.Any(ud => ud.Type == "A"))
.ToList();
int numberOfDesktopAUsers = hasDesktopAUsers.Count;

Linq Value cannot be null on FK

Using C# MVC5 Visual studio 2015.
I have a method that contains the following code:
public List<OffersOnPropertyViewModel> Build(string buyerId)
{
var filtered = _context.Properties.Where(x => x.Offers.Any(c => c.BuyerUserId == buyerId)).ToList();
var model = filtered.Select(c =>
{
var item = new OffersOnPropertyViewModel()
{
PropertyType = c.PropertyType,
NumberOfBedrooms = c.NumberOfBedrooms,
StreetName = c.StreetName,
Offers = c.Offers.Where(d => d.BuyerUserId == buyerId).Select(x => new OfferViewModel
{
Id = x.Id,
Amount = x.Amount,
CreatedAt = x.CreatedAt,
IsPending = x.Status == OfferStatus.Pending,
Status = x.Status.ToString(),
BuyerUserId = x.BuyerUserId
}),
};
return item;
}).ToList();
//TODO: refactor, shorten linq, duping where clause
return model;
}
Here is the model:
public class Property
{
[Key]
public int Id { get; set; }
[Required]
public string PropertyType { get; set; }
[Required]
public string StreetName { get; set; }
[Required]
public string Description { get; set; }
[Required]
public int NumberOfBedrooms { get; set; }
[Required]
public string SellerUserId { get; set; }
public bool IsListedForSale { get; set; }
public ICollection<Offer> Offers { get; set; }
}
In the DB Offers table has the property id as its FK.
The method fails at runtime saying the Value cannot be null.
When I step through I notice the filtered results (in the example its 1 result), is saying offers is null. Although the query just filtered the results based on "x.Offers".
I simply need a way to retrieve a list of property's that have offers made by the buyerId provided. Is my approach wrong? or am i missing a one liner?
Thanks
You will need to add Include() to your LINQ query to bring in child objects, as follows:
var filtered = _context.Properties.Include("Offers")
.Where(x => x.Offers.Any(c => c.BuyerUserId == buyerId)).ToList();
The reason your filter works with the Any() is because when generating the SQL query, this part forms the WHERE clause and is not included in the SELECT.

ServiceStack OrmLite Include Column in Where Clause but Not Select

Consider the LoyaltyCard database DTO I have below:
[Alias("customer_ids")]
[CompositeIndex("id_code", "id_number", Unique = true)]
public class LoyaltyCard
{
[Alias("customer_code")]
public int CustomerId { get; set; }
[Alias("id_code")]
public string LoyaltyCardCode { get; set; }
[Alias("id_number")]
public string LoyaltyCardNumber { get; set; }
[Alias("date_issued ")]
public DateTime? IssueDate { get; set; }
[Alias("linked_id")]
public bool LinkedId { get; set; }
[Alias("positive_id")]
public bool PositiveId { get; set; }
}
I have CustomerId as a property because I need it to be included in the WHERE clause of the generated SQL, but I don't want the column to also be selected in the result set. Is there a way to include it in the where but exclude it from the select?
// I was hoping that result would not have a populated CustomerIds
var result = db.Select<LoyaltyCard>(id => id.LoyaltyCardCode == "PS" && id.CustomerId == customerCode);
I've tried adding the [Ignore] attribute but that fails with SqlException: Invalid column name 'CustomerId'.
If you don't want the entire POCO populated you'd need to specify a Custom Select with just the fields you want selected, e.g:
var result = db.Select<LoyaltyCard>(db.From<LoyaltyCard>()
.Where(id => id.LoyaltyCardCode == "PS" && id.CustomerId == customerCode)
.Select(x => new {
x.LoyaltyCardCode,
x.LoyaltyCardNumber,
x.IssueDate,
x.LinkedId,
x.PositiveId
}));

Add data to a list insde a list where item in the prerent list

I would like to select a where statement that adds items to a list where only product codes match. I have it so it gets all of the products sold in the sale but I would like there were statement to get only products in this sale.
PS: This is really hard to explain
Model
public class userSales
{
public string Name { get; set; }
public string UserName { get; set; }
public int Sale_Id { get; set; }
public int CostumerID { get; set; }
public string Sale_Date { get; set; }
public string Paid { get; set; }
public Nullable<int> Sale_Cost { get; set; }
public string Discount_Code { get; set; }
public List<SaleProduct> saleProductsList { get; set; }
}
public class SaleProduct
{
public int SaleID { get; set; }
public string ProductCode { get; set; }
public int ProductCount { get; set; }
public string Image_Path { get; set; }
public string Shoot_Date { get; set; }
public string Shoot_Info { get; set; }
}
Linq statement where I'm having trouble:
var test = (from _ClientData in db.ClientDatas
join _salesInfo in db.Sales_Infoes
on _ClientData.CostumerID
equals _salesInfo.CostumerID
where _ClientData.UserName == _userName
select new userSales()
{
CostumerID = _ClientData.CostumerID,
Name = _ClientData.Name,
UserName = _ClientData.UserName,
Sale_Id = _salesInfo.Sale_Id, // This is the item i would like to use in my were statement
Sale_Date = _salesInfo.Sale_Date,
Sale_Cost = _salesInfo.Sale_Cost,
Discount_Code = _salesInfo.Discount_Code,
Paid = _salesInfo.Paid,
// Problem here
saleProductsList = db.SaleProducts.Where()
}).ToList();
Got to this based on the answer:
var reult = db.ClientDatas.Where(a => a.UserName == _userName)
.Join(db.Sales_Infoes,
a => a.CostumerID,
b => b.CostumerID,
(a, b) => new userSales()
{
CostumerID = a.CostumerID,
Discount_Code = b.Discount_Code,
Sale_Cost = b.Sale_Cost,
Sale_Id= b.Sale_Id,
Name = a.Name,
Sale_Date = b.Sale_Date,
UserName = a.UserName,
Paid = b.Paid,
saleProductsList = db.SaleProducts.Where(c => c.SaleID == b.Sale_Id).ToList()
}).ToList();
You're not looking for a where, you're looking for a join. Where filters the results on a single table, join intersects two tables which is actually what you want here.
var result = db.Sales_Infoes.Where(x => x.UserName == _userName)
.Join(db.ClientDatas,
x => x.Sale_Id,
y => y.Sale_id,
(x, y) => new userSales() {
// x is SalesInfo obj y is ClientDatas obj do assignement here
Name = y.Name,
Sale_Date = y.Sale_date
}).ToList();
Just fyi I haven't had a chance to test that but it's the basic idea. You don't need a select like in your statement because the last argument I'm passing into join is the lambda (x, y) => ... in that case x and y are the current row from each table (that we've gotten from applying our where to the user sales table then joining those results into the salesproduct table) so whatever projections you want to do occur there. The other two method args above that are the telling join which fields to compare, it's the 'key selector' lambda expression for each table.

Using a calculated value in the OrderBy clause with EF

I'm trying to use a calculated value in my OrderBy clause in a LINQ query.
The error I am getting is:
DbArithmeticExpression arguments must have a numeric common type.
My model looks like this:
public class PostModel
{
public int ID { get; set; }
public DateTime Created { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string FilePath { get; set; }
public float Rank { get; set; }
public UserProfile Creator { get; set; }
public bool ShowPost { get; set; }
public PostModel()
{
Created = DateTime.Now;
Rank = 0;
ShowPost = false;
}
}
and I'm trying to select posts using this:
var todaysDate = DateTime.Now.AddDays(-10);
var result = _database.Posts
.Where(p => p.ShowPost == true)
.OrderBy(x => ((float)x.Rank) - (((float)(x.Created - todaysDate).TotalDays)) / 2f)
.Skip(page * StaticVariables.ResponseDataPageSize)
.Take(StaticVariables.ResponseDataPageSize)
.Select(s => new
{
id = s.ID,
rank = s.Rank,
title = s.Title,
description = s.Description
}
);
It's the order by causing the error. I first thought it was that I was not casting all my variables to the same type, but adding (float) does not seem to help.
The purpose of the code is to make make high ranking posts fall down the list over time as to allow newer information to be shown.
Any ideas?
Use EntityFunctions in LinqToEntity:
EntityFunctions.DiffDays(todaysDate, x.Created)

Categories

Resources