How do I convert this SQL to Linq? [duplicate] - c#

This question already has an answer here:
SQL to LINQ with multiple join, count and left join
(1 answer)
Closed 2 years ago.
What would this SQL look like in Linq?
You can see the SQL statement that I want to use, I am pretty new to Linq:
SELECT user_id
FROM profiles
LEFT JOIN interests ON profiles.id = interests.profile_id
WHERE interest IN ('Shopping', 'Art')
AND Sex IN ('Man', 'Woman')
AND user_id NOT IN (SELECT user_1 FROM matches)
AND user_id != 84
GROUP BY user_id
ORDER BY COUNT(user_id) DESC;
Beneath you can see the different models, All the models have an id from modelbase
Profile model:
namespace Sparks.Presentation.Entities
{
public partial class Profile: ModelBase
{
public Profile()
{
Interests = new HashSet<Interest>();
}
public int UserId { get; set; }
public string Name { get; set; }
public string Picture { get; set; }
public string Birthdate { get; set; }
public string Sex { get; set; }
public string Orientation { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Interest> Interests { get; set; }
[NotMapped]
public IFormFile FormFile { set; get; }
}
}
Interest model:
namespace Sparks.Presentation.Entities
{
public partial class Interest: ModelBase
{
public int ProfileId { get; set; }
public string InterestName { get; set; }
public virtual Profile Profile { get; set; }
}
}
Matchmodel:
namespace Sparks.Presentation.Entities
{
public partial class Match: ModelBase
{
public Match()
{
Chats = new HashSet<Chat>();
}
public int User1 { get; set; }
public int User2 { get; set; }
public bool Matchstatus { get; set; }
public bool Matchmade { get; set; }
public DateTime CreatedOn { get; set; }
public virtual User User1Navigation { get; set; }
public virtual User User2Navigation { get; set; }
public virtual ICollection<Chat> Chats { get; set; }
}
}
Hope someone can help me out?

This is closer to the query what is expected. Looks similar as SQL but select part is last statement.
var interestFilter = new [] {"Shopping", "Art"};
var sexFilter = new [] {"Man", "Woman"};
var query =
from p in ctx.Profiles
from i in p.Interests
where interestFilter.Contains(i.InterestName) && sexFilter.Contains(p.Sex)
&& !ctx.Matches.Any(m => m.User1 == u.UserId)
&& p.UserId != 84
group p by p.UserId into g
order by g.Count()
select g.Key;
var result = query.ToList();

Related

Selection for Linq Query

How can I select the List of ExtrasName and ExtrasId in the following query.
The query contains some mathematical operations aswell.
var query =
from a in _context.Cities
from b in a.CityExtras
where a.CityId == CityId && extraIds.Contains(b.ExtrasId)
group new { a, b } by new { a.PricePerSqM , a.Name, a.CityId , } into g
select new
{
City = g.Key.Name,
PricePerSqM = g.Key.PricePerSqM,
TotalPrice = g.Sum(x => x.b.Price) + g.Key.PricePerSqM * squareMeter
};
My Models are:
public class Extras
{
public int ExtrasId { get; set; }
[Required]
public string ExtrasName { get; set; }
public ICollection<CityExtras> CityExtras { get; set; }
}
public class City
{
public int CityId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int PricePerSqM { get; set; }
public ICollection<CityExtras> CityExtras { get; set; }
}
public class CityExtras
{
public int CityId { get; set; }
public City City { get; set; }
public Extras Extras { get; set; }
public int ExtrasId { get; set; }
public int Price { get; set; }
}
I need ExtrasNames and ExtrasId in the query
As they stand, your models are not going to allow you to do this easily. You should add navigation properties to your models, then your Linq will be much cleaner (no need for the double select), and you will be able to navigate upwards to the Extra object and get the data you want.

How to join two tables and fetch data from

I have two tables from which I want to fetch the data and return it to the API for consumable purposes. There is a relationship between the two tables.
[![enter image description here][1]][1]
When I try to fetch the data, it is returning only one row which is not what I want.
How can I return all the data related to ResellerId (8435 examples)?
This is my code:
public RateSheetModel GetRateSheet(int resellerId)
{
// This only returns only one row.
// How can I get all rows for all the same Id?
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
where r.ResellerId == resellerId
select r).First();
}
Models
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join rateSheet in _Context.<tableName> on r.ResellerId equals rateSheet.ResellerId
where r.ResellerId == resellerId
select new { foo });
You're making a new type by doing this, as a combination of data from both tables. You can either define a model class and use something like
select new MyClass {
Foo = r.RateSheetMarkupId,
Bar = rateSheet.RateSheetName
}
Otherwise, no class definition is required. Simply using 'new' without a class will create an anonymous type with properties that match what you're selecting. The example here could be more precise if you share the entity names.
Altogether, going off your code:
public List<RateSheetModel> GetRateSheet(int resellerId)
{
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join m in _Context.RateSheetMarkup on r.ResellerId equals m.ResellerId
where r.ResellerId == resellerId
select new RateSheetModel {
ResellerId = r.ResellerId
RatesheetName = m.RatesheetName
};
return rateSheetDetails.ToList<RateSheetModel>;
}
public RateSheetModel { //dunno what this model looks like, but example
public int ResellerId {get; set;}
public string RatesheetName {get; set;}
}

LINQ: Search/Filter data from multiple table

I have three tables,
Table:1
UserId UserName ...
1 Jhon ...
2 Ashley ...
3 Alexa ...
4 Krish ...
Table:2
BrandId UserId BrandName
1 1 BMW
2 1 Citroen
3 2 Audi
4 4 Peugeot
Table:3
CountryId UserId CountryName
1 3 Austria
Now what I want if user search items by Brands = ["BMW", "Audi"] & Countries= ["India","Romania"] then it should show the user result like :
UserId UserName ...
1 Jhon ...
2 Ashley ...
or search items by only Countries= ["India","Austria"] then result should be :
UserId UserName ...
3 Alexa ...
I have tried like following C#-LINQ, But I am always getting all user data. It's not filtering based on the given Brand or Country input. So it should give the data if either Brands or Countries match with DB data. It's not giving properly even if I remove the "into" from the LINQ part. Where Did I go wrong?
var users = new List<Users>();
users = _DbContext.Users.Where(x => x.Roles == model.Role).ToList();
users = (from p in users
join b in _DbContext.UserBrands.Where(x => model.arBrands.Contains(x.BrandName)).ToList() on p.UserSequence equals b.UserId into bg
join c in _DbContext.UserCountries.Where(x => model.arCountries.Contains(x.CountryName)).ToList() on p.UserSequence equals c.UserId into cg
select p).ToList();
And my Sample Payload,
{
"arBrands": ["Citroen","Peugeot"],
"arCountries":["India","Romania"],
"Role":"All Roles"
}
Entities:
public class UserBrands
{
[Key] public virtual int UserBrandsId { get; set; }
public virtual int UserId { get; set; }
public virtual int BrandId { get; set; }
public virtual string BrandName { get; set; }
}
public class UserCountries
{
[Key] public virtual int UserCountriesId { get; set; }
public virtual int UserId { get; set; }
public virtual int CountryId { get; set; }
public virtual string CountryName { get; set; }
}
public class UsersModel
{
public string[] arCountries { get; set; }
public string[] arBrands { get; set; }
[Required]
public string Role { get; set; }
public List<LeafLet> features { get; set; }
}
public class Users : BaseEntity
{
[Key]
public virtual int UserSequence { get; set; }
public virtual string UserName { get; set; }
public virtual string Countries { get; set; }
public virtual string Brands { get; set; }
public virtual string Email { get; set; }
public virtual string Latitude { get; set; }
public virtual string Longitude { get; set; }
public virtual string ProjectRole { get; set; }
public virtual string Roles { get; set; }
}
You will need to clean up your models a bit, and add navigation properties to let EF perform the joins for you.
public class Users
{
[Key]
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Role { get; set; }
//Only use the virtual keyword for navigating properties to other entities.
public virtual IEnumerable<UserBrand> UserBrands {get; set;}
public virtual IEnumerable<UserCountry> UserCountries {get; set;}
}
public class UserBrand
{
[Key]
public int Id { get; set; }
public int UserId { get; set; }
public int BrandId { get; set; }
[ForeignKey("UserId")] // lets Entity Framework know how to map the navigation.
public virtual User User { get; set; }
[ForeignKey("BrandId")]
public virtual Brand Brand { get; set; }
}
public class Brand
{
[Key]
public int Id { get; set; }
public string BrandName { get; set; }
}
public class UserCountry
{
[Key]
public int Id { get; set; }
public int UserId { get; set; }
public int CountryId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
[ForeignKey("CountryId")]
public virtual Country Country { get; set; }
}
public class Country
{
[Key]
public int Id { get; set; }
public string CountryName { get; set; }
}
Your LINQ query will then look something like this:
var users = _DbContext.Users
.Where(u => u.Role == model.Role)
.Select(u => new {
UserName = u.UserName,
Email = u.Email,
Role = u.Role,
BrandNames = u.UserBrands.Select(ub => ub.Brand.BrandName),
Countries = u.UserCountries.Select(uc => uc.CountryName)
}).ToList();
You can add more filters to the Where clause using the navigation properties:
var users = _DbContext.Users
.Where(u => u.Role == model.Role
&& u.UserBrands.Any(ub =>
ub.Brand.BrandName == "Brand X") //Filter for brand name.
&& u.UserCountries.Any(uc =>
uc.Country.CountryName == "United States") //Filter for brand name.
.Select(u => new {
UserName = u.UserName,
Email = u.Email,
Role = u.Role,
BrandNames = u.BrandNames,
Countries = u.Countries
})
.ToList();

Calculate Account Receivables using LINQ

How to calculate account receivable using LINQ.
I have tried this but stuck here.
I have done this in SQL but I want this in LINQ so I can use it in my MVC project.
var sale = saleslist.GroupBy(s => s.BuyerId).Select(s => s.Sum(u => u.Amount)).ToList();
var receipt = receiptslist.GroupBy(r => r.StakeHolderId).Select(t => t.Sum(u => u.Amount)).ToList();
List<AccountReceivablesVM> res = db.StakeHolders
.Where(r=>r.StakeHolderTypeId == "0b85a69e-55f2-4142-a49d-98e22aa7ca10")
.Select(rvm => new AccountReceivablesVM
{
CompanyName = rvm.CompanyName,
Receivables = //don't know what to do here
}).ToList();
Models:
public class StakeHolder
{
public string StakeHolderId { get; set; }
public string CompanyName { get; set; }
public string Address { get; set; }
public string Contact { get; set; }
public string StakeHolderTypeId { get; set; }
}
public class Sale
{
public string SaleId { get; set; }
public string RefNo { get; set; }
public DateTime Date { get; set; }
public string BuyerId { get; set; }
public string Description { get; set; }
public Nullable<double> Amount { get; set; }
}
public class PaymentsAndReceipt
{
public string PaymentAndReceiptId { get; set; }
public Nullable<int> VoucherNo { get; set; }
public DateTime Date { get; set; }
public string StakeHolderId { get; set; }
public string Description { get; set; }
public Nullable<double> Amount { get; set; }
}
public class AccountReceivablesVM
{
public string CompanyName { get; set; }
public Nullable<double> Receivables { get; set; }
}
Expected Result:
You can join first with stakeholderId and then sum the amount and then group by with company name and stakeholder id, however I write the code in Linq. I have considered the stakeholderid as the primary key of your table just because you have not mentioned the schema of stakeholder so.
var result = from s in db.StakeHolders
join pr in db.PaymentsAndReceipt on s.StakeHolderId equals pr.StakeHolderId
where StakeHolderTypeId == "0b85a69e-55f2-4142-a49d-98e22aa7ca10"
group s by new { s.StakeHolderId,s.CompanyName} into p
select new
{
StakeHolderId= p.Key.StakeHolderId,
CompanyName= p.Key.CompanyName,
Receivables = string.Format("{0:C}", p.Sum(y => y.Amount))
};

LINQ query to get count of joined record

Can somebody help me out writing a LINQ query to get record that are joined? I have two models below. I want to get requirements count that belong to given project and has one or more ProjectTest joined to it.
public class ProjectTest
{
public int ProjectTestID { get; set; }
public int ProjectID { get; set; }
public String Objective { get; set; }
public String Category { get; set; }
public String SubCategory { get; set; }
public String Tags { get; set; }
public virtual ICollection<ProjectRequirement> ProjectRequirements { get; set; }
public virtual ICollection<ProjectTestStep> ProjectTestSteps { get; set; }
}
public class ProjectRequirement
{
public int ProjectRequirementID { get; set; }
public int ProjectID { get; set; }
[Display(Name = "Req No.")]
public String ProjectRequirementIDStr { get; set; }
[Display(Name = "Module")]
public String ModuleName { get; set; }
[Display(Name = "Description")]
public String Description { get; set; }
public virtual ICollection<ProjectTest> ProjectTests { get; set; }
}
I just tried to write it as follows but does not seem working.
db.ProjectRequirements
.Where(e => e.ProjectID == activeProjectID &&
e.ProjectTests
.Select(ept => ept.ProjectTestID)
.Count() > 0)
.Select(e => e.ProjectRequirementID)
.Count();
Currently you are counting the number of ProjectRequirement objects that have a given id and that have at least 1 ProjectTest.
If you want to count the amount of ProjectTests you have for a given ProjectId:
var number = db.ProjectRequirements.Where(e => e.ProjectID == activeProjectID)
.Sum(e => e.ProjectTests.Count());

Categories

Resources