LINQ Query to join three tables - linq

I need a help in LINQ Query for the below.
public interface IBrand
{
int BrandId { get; set; }
IEnumerable<IBuyingAgency> BuyingAgencies { get; set; }
}
public interface IBuyingAgency
{
int BuyingAgencyId { get; set; }
}
public interface IClientGroup
{
IBuyingAgency BuyingAgency { get; set; }
int ClientGroupId { get; set; }
}
1). var brands = LoggedInUserHelper.GetUser().GetBrands(roles); // returns IEnumerable<Tuple<IBrand, string>>
2). var buyingAgencies = LoggedInUserHelper.GetUser().GetBuyingAgencies(roles); //IEnumerable<IBuyingAgency>
3). var clientGroups = LoggedInUserHelper.GetUser().GetClientGroups(roles); //IEnumerable<IClientGroup>
function IEnumerable<IClientGroup> GetClientGroups( List<int> BrandIds)
{
var brands = LoggedInUserHelper.GetUser().GetBrands(roles); // returns IEnumerable<Tuple<IBrand, string>>
var buyingAgencies = LoggedInUserHelper.GetUser().GetBuyingAgencies(roles); //IEnumerable<IBuyingAgency>
var clientGroups = LoggedInUserHelper.GetUser().GetClientGroups(roles); //IEnumerable<IClientGroup>
var lstBrandagencies = brands.Where(brand => BrandIds.Contains(brand.Item1.BrandId) && brand.Item1.BuyingAgencies.Any( ba => buyingAgencies.Contains(ba.BuyingAgencyId))).SelectMany(brand => brand.Item1.BuyingAgencies);
var buyingAgencyIDs = lstBrandagencies.Select(b => b.BuyingAgencyId);
clientGroups = clientGroups.Where(cg => buyingAgencyIDs.Contains(cg.BuyingAgency.BuyingAgencyId));
return Mapper.Map<IEnumerable<IClientGroup>>(clientGroups.ToList());
}
I wrote the above function but not working, it gets all the clientgroups instead of filtering
I wants to write a query to get all ClientGroups whch satisfies the below condition
1. retrieve the brand from brands ( above ) that matches the list of brandId's passing in as parameter
2. Than get all the buyingAgencies under brands (1) above which matches with the id's of (2) above
3. Finally get all clientgroups which matches with the buyingAgency retrieving in step (2)
Please can you help.

you are not filtering from your source 2) in this line
var buyingAgencyIDs = lstBrandagencies.Select(b => b.BuyingAgencyId);
just projecting from the previous query.
If I understood correctly you want to do this.
var lstBrandagencies = (from a in brands
where BrandIds.Contains(a.Item1.BrandId )
select a).SelectMany (b => b.Item1.BuyingAgencies )
.Select (b => b.BuyingAgencyId );
var buyingAgencyIDs = from a in buyingAgencies
where lstBrandagencies.Contains(a.BuyingAgencyId )
select a.BuyingAgencyId;
var clientGroupsResult = clientGroups.Where(cg => buyingAgencyIDs.Contains(cg.BuyingAgency.BuyingAgencyId));

Related

how to add the number of items at the end of the linq query

i have the following LINQ
public IEnumerable<TurbineStatus> turStatus()
{
var result = (from s in _db.masterData
group s by s.current_turbine_status into g
select new TurbineStatus
{
status = g.Key,
numberOfTurbines = g.Count()
}
).ToList().OrderByDescending(s => s.status);
return result;
}
my class:
public class TurbineStatus
{
public string status { get; set; }
public int numberOfTurbines { get; set; }
public int allTurbines { get; set; }
}
i gives me the number of turbines according to the status,for example, 5turbines STOP,6 turbines RUN,10 turbines Link Down and so on,i also need to have sum of all these statuses,in my TurbinesStatus class i have a field which is int and named it allTurbines,how can i achieve it?
It's probably better for performance reasons to let the DB handle sorting and then once the result is materialized, you can extract the sum of the turbines count:
var result =
(
from s in _db.masterData
group s by s.current_turbine_status into g
select new TurbineStatus
{
status = g.Key,
numberOfTurbines = g.Count()
} into statusGroup
orderby statusGroup.status descending
select statusGroup
).ToList();
int totalTurbines = groups.Sum(statusGroup => statusGroup.numberOfTurbines);
To return both as a TurbinesStatus instance:
public class TurbinesStatus
{
public IReadOnlyList<TurbineStatus> TurbineStatuses { get; }
public int TotalCount { get; }
public TurbinesStatus(IReadOnlyList<TurbineStatus> turbineStatuses)
{
TurbineStatuses = turbineStatuses;
TotalCount = turbineStatuses.Sum(ts => ts.numberOfTurbines);
}
}
and then
public TurbinesStatus turStatus()
{
var statuses =
(
from s in _db.masterData
group s by s.current_turbine_status into g
select new TurbineStatus
{
status = g.Key,
numberOfTurbines = g.Count()
} into statusGroup
orderby statusGroup.status descending
).ToList();
return new TurbinesStatus(statuses);
}

Get List Data of selected Column from Table

I want to get data of selected columns from a table and return that data in repository class. But my query does not return any data.
My Code is:
public IQueryable<BusinessProfile> GetBusinessProfileAddress()
{
var y = _db.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new
{
x.ID,
x.Address.StreetName,
x.Address.Number,
x.Address.Complement,
x.Address.PostalCode,
x.Address.Neighborhood,
x.Address.City,
x.Address.State
});
var d=from a in BusinessProfile select a.
return y; ;
}
Note: Here "return y" is in showing error.
This code won't even build because you haven't finished this query: var d=from a in BusinessProfile select a., but, you are not using the d variable at all so you should remove the whole var d=from a in BusinessProfile select a. line. And you don't need 2 semicolons after y. So, your code should look like this:
public IQueryable GetBusinessProfileAddress() {
var y = _db.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new
{
x.ID,
x.Address.StreetName,
x.Address.Number,
x.Address.Complement,
x.Address.PostalCode,
x.Address.Neighborhood,
x.Address.City,
x.Address.State
});
return y;
}
For your current code, you will get error like
Cannot implicitly convert type 'System.Linq.IQueryable<>' to 'System.Linq.IQueryable'. An explicit conversion exists
If you want to return the new type, you may consider define a new model and change BusinessProfile.
public IQueryable<BusinessProfileVM> GetBusinessProfileAddress()
{
var y = _appDbContext.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new BusinessProfileVM
{
Id = x.Id,
StreetName = x.Address.StreetName,
});
return y;
}
public class BusinessProfileVM
{
public int Id { get; set; }
public string StreetName { get; set; }
}

LINQ GroupBy month

I am having trouble getting an IQueryable list of a (subsonic) object grouped by Month and Year.
Basic view of the object...
public partial class DatabaseObject
{
[SubSonicPrimaryKey]
public int objectID { get; set; }
public string Description { get; set; }
public decimal Value { get; set; }
public string Category { get; set; }
public DateTime DateOccurred { get; set; }
}
Method to get IQueryable in my Database repository...
public IQueryable GetData(string DataType)
{
return (from t in db.All<DatabaseObject>()
orderby t.DateOccurred descending
select t)
.Where(e => e.Category == DataType);
}
My question is, how can I return the dates grouped by Month? I have tried the below, but this results in compiler warnings regarding anonymous types...
public IQueryable GetData(string DataType)
{
var datalist = (from t in db.All<FinancialTransaction>().Where(e => e.Category == DataType);
let m = new
{
month = t.DateOccurred.Month,
year = t.DateOccurred.Year
}
group t by m into l select new
{
Description = string.Format("{0}/{1}", l.Key.month, l.Key.year),
Value = l.Sum(v => v.Value), // Sum(v => v.Value),
Category = "Grouped"
DateOccurred = l.Last(v => v.DateOccurred)
}
return datalist;
}
Any ideas?
Try this couple issues i found, but you basically need to select a Database object versus anonymous type?
IQueryable<DatabaseObject> datalist = (
from t in db.All<FinancialTransaction>().Where(e => e.Category == DataType)
let m = new
{
month = t.DateOccurred.Month,
year = t.DateOccurred.Year
}
group t by m into l
select new DatabaseObject()
{
Description = string.Format("{0}/{1}", l.Key.month, l.Key.year),
Value = l.Sum(v => v.Value), //Sum(v => v.Value),
Category = "Grouped",
DateOccurred = l.Max(v => v.DateOccurred)
}).AsQueryable();
Let me know if my solution is now what you want. I also noticed you were using Last? The extension you were using I do not have so I replaced it with Max. I don't have subsonic installed so it might come with the libraries.
Any way don't combine LINQ in query syntax and LINQ in extension methods syntax. Use next:
from t in db.All<DatabaseObject>()
where e.Category equals DataType
orderby t.DateOccurred descending
select t;
The issue is apparantly to do with the way Subsonic interprests certain linq statements and is a known bug.
IEnumerable<DatabaseObject> datalist = (
from t in db.All<FinancialTransaction>().Where(e => e.Category == DataType).ToList()
let m = new
{
month = t.DateOccurred.Month,
year = t.DateOccurred.Year
}
group t by m into l
select new DatabaseObject()
{
Description = string.Format("{0}/{1}", l.Key.month, l.Key.year),
Value = l.Sum(v => v.Value), //Sum(v => v.Value),
Category = "Grouped",
DateOccurred = l.Max(v => v.DateOccurred)
}).AsQueryable();
I have fixed this by declaring an list of type IEnumerable and using ToList() to cast the database interaction, finally the query is then recast AsQueryable()

linq count/groupby not working

I want to group by the categoryid and then do a count on this. But I don't know how to do this. I have tried a couple of ways without success. Here is my latest:
public class Count
{
public int TradersCount { get; set; }
public int Id { get; set; }
public string Description { get; set; }
}
public IQueryable<Count> CountTradersAttachedToCategories()
{
var data = from tc in _db.tblTradersCategories
select new Count
{
Description = tc.tblCategory.description,
Id = tc.tblCategory.categoryId,
TradersCount = tc.Select(x => x.categoryid).GroupBy().Count()
};
return data;
}
tblTradersCategories joins both
tblTraders/tblCategories
A single trader can have many categories
A single category can have many traders
Thanks in advance for any help.
Clare
Try this:
var data = from tc in _db.tblTradersCategories
group tc by new { tc.tblCategory.categoryId,
tc.tblCategory.description } into g
select new { Count = g.Count(),
Id = g.Key.categoryId,
Description = g.Key.description };
If you want that in your Count class you may need to use AsEnumerable() to perform the conversion in process:
var converted = data.AsEnumerable()
.Select(c => new Count { TradersCount = c.Count,
Id = c.Id,
Description = c.Description });
You can try doing them all in one go:
var data = from tc in _db.tblTradersCategories
group tc by new { tc.tblCategory.categoryId,
tc.tblCategory.description } into g
select new Count { TradersCount = g.Count,()
Id = g.Key.categoryId,
Description = g.Key.description };
But I don't know if that will work. It depends on how the LINQ provider handles it.

How do I add a where filter using the original Linq-to-SQL object in the following scenario

I am performing a select query using the following Linq expression:
Table<Tbl_Movement> movements = context.Tbl_Movement;
var query = from m in movements
select new MovementSummary
{
Id = m.DocketId,
Created = m.DateTimeStamp,
CreatedBy = m.Tbl_User.FullName,
DocketNumber = m.DocketNumber,
DocketTypeDescription = m.Ref_DocketType.DocketType,
DocketTypeId = m.DocketTypeId,
Site = new Site()
{
Id = m.Tbl_Site.SiteId,
FirstLine = m.Tbl_Site.FirstLine,
Postcode = m.Tbl_Site.Postcode,
SiteName = m.Tbl_Site.SiteName,
TownCity = m.Tbl_Site.TownCity,
Brewery = new Brewery()
{
Id = m.Tbl_Site.Ref_Brewery.BreweryId,
BreweryName = m.Tbl_Site.Ref_Brewery.BreweryName
},
Region = new Region()
{
Description = m.Tbl_Site.Ref_Region.Description,
Id = m.Tbl_Site.Ref_Region.RegionId
}
}
};
I am also passing in an IFilter class into the method where this select is performed.
public interface IJobFilter
{
int? PersonId { get; set; }
int? RegionId { get; set; }
int? SiteId { get; set; }
int? AssetId { get; set; }
}
How do I add these where parameters into my SQL expression? Preferably I'd like this done in another method as the filtering will be re-used across multiple repositories.
Unfortunately when I do query.Where it has become an IQueryable<MovementSummary>. I'm assuming it has become this as I'm returning an IEnumerable<MovementSummary>. I've only just started learning LINQ, so be gentle.
Answer:
private IQueryable<Tbl_Docket> BuildQuery(IQueryable<Tbl_Docket> movements, IMovementFilter filter)
{
if (filter != null)
{
if (filter.PersonId.HasValue) movements = movements.Where(m => m.UserId == filter.PersonId);
if (filter.SiteId.HasValue) ...
}
return movements;
}
Which is called like follows:
var query = from m in this.BuildQuery(movements, filter)
select new... {}
You have to call the where statement before you fire your select statement, e.g.:
IQueryable<Tbl_Movement> movements = context.Tbl_Movement;
if (filter != null)
{
if (filter.PersonId != null) movements = movements.Where(m => m....PersonId == filter.PersonId);
if (filter.RegionId != null) movements = movements.Where(m => m....RegionId == filter.RegionId);
if (filter.SiteId != null) movements = movements.Where(m => m...SiteId == filter.SiteId);
if (filter.AssetId != null) movements = movements.Where(m => m...AssetId == filter.AssetId);
}
var query = m from movements...
As opposed to using this IFilter class, you might want to consider a Fluent Pipe-based Repository structure, e.g.:
var movements = new MovementsPipe()
.FindSiteId(1)
.FindAssetIds(1, 2, 3)
.FindRegionId(m => m > 10)
.ToMovementSummaryList();
Hope this helps. Let me know if you have any questions.

Resources