Convert SQL Command to lambda expression - entity-framework

If possible, please guide me how to convert my SQL command to lambda expression
select d.* from takcontractdet d where d.contractid=pubcontractid and d.personid in
(
select p.id from personel p where p.parentid=pubparentid)
)

Two query
var personelIds = Personels.Where(p => p.ParentId == pubparentid)
.Select(e => e.Id).ToList();
var result = Takcontractdets.Where(d => d.contractid == pubcontractid &&
personelIds.Contains(d.PersonId)).ToList();
One query
var result = Takcontractdets.Where(d => d.contractid == pubcontractid &&
Personels.Where(p => p.ParentId == pubparentid)
.Select(e => e.Id).ToList().Contains(d.PersonId))
.ToList();

Related

EF Core - Order by on filtered left join properties

I would like to generate this SQL query in entity framework
SELECT FunctionalAssets.Name, FunctionalAssetStructurePath.Path
FROM FunctionalAssets
LEFT JOIN FunctionalAssetStructurePath ON FunctionalAssets.Id =
FunctionalAssetStructurePath.FunctionalAssetId AND
FunctionalAssetStructurePath.StructureConfigurationId = 'A8A41B14-0A35-45D3-2A2B-08D904A3CD0B'
ORDER BY FunctionalAssetStructurePath.Path, FunctionalAssets.Name
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY
I try with this code (but I know that it won't work)
var result = context.FunctionalAssets
.Include(x => x.FunctionalAssetsStructurePaths.Any(y => y.StructureConfigurationId == configurationId))
.OrderBy(x => x.FunctionalAssetsStructurePaths.Select(y => y.Path))
.ThenBy(x => x.Name)
.Skip(0)
.Take(100)
.AsNoTracking()
.Select(x => x.Name)
.ToList();
Have you an idea how to do this ?
Thank you
I found a solution.
var result = context.FunctionalAssets
.GroupJoin(context.FunctionalAssetStructurePathModel.Where(y => y.StructureConfigurationId == 'A8A41B14-0A35-45D3-2A2B-08D904A3CD0B'),
fa => fa.Id,
fasp => fasp.FunctionalAssetId,
(fa, fasp) => new { fa, fasp })
.SelectMany(x => x.fasp.DefaultIfEmpty(), (x, p) => new { x.fa, p.Path })
.OrderBy(x => x.Path)
.Skip(0)
.Take(100)
.ToList();
And the generated SQL query is :
SELECT [f].[Id], [f].[Name], [t].[Path]
FROM [FunctionalAssets] AS [f]
LEFT JOIN (
SELECT [f0].[FunctionalAssetId], [f0].[Path]
FROM [FunctionalAssetStructurePath] AS [f0]
WHERE [f0].[StructureConfigurationId] = 'A8A41B14-0A35-45D3-2A2B-08D904A3CD0B'
) AS [t] ON [f].[Id] = [t].[FunctionalAssetId]
ORDER BY [t].[Path]
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY

Linq EF --> Contains condition does not work

I have a problem: I have this table
ID
Title
GenreID
Genre
Duration
1
Movie1
1,2
Cartoon, Family
80
2
Movie2
3,4
Horror, Drama
76
3
Movie3
4
Drama
110
4
Movie4
1,2
Cartoon, Family
200
I need to filter by Genre, I make my query in this way, For example if I want all movies with Genre Cartoon (2), I make:
request.genre = 2
var query1 = from q in Movies
select new Response.MovieResponse
{
MovieId = q.MovieId,
Name = q.Title,
Genres = q.Genre,
GenreIds = q.GenreID
};
if (request != null)
{
if (!string.IsNullOrEmpty(request.Title))
query1 = query1.Where(co => co.Name.StartsWith(request.name));
if (!string.IsNullOrEmpty(request.genre))
if (int.Parse(request.genre) > 0)
{
query1.AsEnumerable().Where(ca =>
request.genre .Any(x => ca.GenreIds.Contains(x)));
}
}
List<Response.StoreResponse> stores = new List<Response.StoreResponse>();
stores = await query1.ToListAsync();
I expected 2 records inside but the filter on genre does not work. I always have back all movies. The filter by title run
I tried
if (!string.IsNullOrEmpty(request.category))
if (int.Parse(request.category) > 0)
{
string[] cat = { request.category };
var q1 = query1.Where(ca => ca.CategoriesIds.Contains(cat.ToString()));
l = q1.ToList();
}
but I have error:
The LINQ expression 'DbSet<Store>()
.Join(
inner: DbSet<Country>(),
outerKeySelector: s => s.CountryId,
innerKeySelector: c => (Nullable<int>)c.CountryId,
resultSelector: (s, c) => new TransparentIdentifier<Store, Country>(
Outer = s,
Inner = c
))
.Join(
inner: DbSet<City>(),
outerKeySelector: ti => ti.Outer.CityId,
innerKeySelector: c0 => (Nullable<long>)c0.CityId,
resultSelector: (ti, c0) => new TransparentIdentifier<TransparentIdentifier<Store, Country>, City>(
Outer = ti,
Inner = c0
))
.Where(ti0 => ti0.Outer.Outer.StatusId == (Nullable<int>)2)
.Where(ti0 => DbSet<Operator>()
.Where(o => EF.Property<Nullable<Guid>>(ti0.Outer.Outer, "StoreId") != null && object.Equals(
objA: (object)EF.Property<Nullable<Guid>>(ti0.Outer.Outer, "StoreId"),
objB: (object)EF.Property<Nullable<Guid>>(o, "StoreId")))
.Count() > 0)
.Where(ti0 => string.Join<long>(
separator: ",",
values: DbSet<StoresCategory>()
.Where(s0 => EF.Property<Nullable<Guid>>(ti0.Outer.Outer, "StoreId") != null && object.Equals(
objA: (object)EF.Property<Nullable<Guid>>(ti0.Outer.Outer, "StoreId"),
objB: (object)EF.Property<Nullable<Guid>>(s0, "StoreId")))
.Select(s0 => s0.CategoryId)
.ToList()).Contains(__ToString_0))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Ef core 5 many to many filter

This is my query
public async Task<IEnumerable<Menu>> GetMenuByRolesAsync(string[] roles)
{
var result= await _context.Menus//.Include(o => o.Parent)
.Include(m => m.Childrens)
.ThenInclude(m => m.Childrens)
.Include(m => m.Roles.Where(r => roles.Contains(r.Name))) --it is not filtering basd on roles
.Where(m => m.ParentId == null)
.ToListAsync();
}
It is generating below query
-- #__roles_0='System.String[]' (DbType = Object)
SELECT m.id, m.icon, m.name, m.parent_id, m.url, t.role_id, t.menu_id, t.id, t.concurrency_stamp, t.name, t.normalized_name
FROM security.menu AS m
LEFT JOIN (
SELECT r.role_id, r.menu_id, r0.id, r0.concurrency_stamp, r0.name, r0.normalized_name
FROM security.role_menu AS r
INNER JOIN security.role AS r0 ON r.role_id = r0.id
WHERE r0.name = ANY (#__roles_0) OR ((r0.name IS NULL) AND (array_position(#__roles_0, NULL) IS NOT NULL))
) AS t ON m.id = t.menu_id
WHERE (m.parent_id IS NULL)
ORDER BY m.id, t.role_id, t.menu_id, t.id
This is Many to many configuration
// many to many
builder.HasMany(r => r.Menus)
.WithMany(r => r.Roles)
.UsingEntity<RoleMenu>(
j => j
.HasOne(rm => rm.Menu)
.WithMany(m => m.RoleMenus)
.HasForeignKey(rm => rm.MenuId),
j => j
.HasOne(rm => rm.Role)
.WithMany(r => r.RoleMenus)
.HasForeignKey(rm => rm.RoleId),
j =>
{
j.ToTable("role_menu", schema: "security");
j.HasKey(rm => new { rm.RoleId, rm.MenuId });
});
i need to filter menus based on roles..But it is not filtering based on roles..Am getting all the roles..I checked generated query..Please let me know what is the issue..
You are mixing filtered include with entity filtering.
Filtered include
.Include(m => m.Roles.Where(r => roles.Contains(r.Name)))
just filters the items in the related collection (menu roles in this case).
In order to filter the entity set (menus in this case), you need to replace it with the usual Where oparator, which for the desired filtering will be
.Where(m => m.Roles.Any(r => roles.Contains(r.Name)))

Entity Framework Core: combining multiple result objects into one collection

I am facing this linq query for entity framework core (2.0).
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.Select
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new
{
singleObject = t2e.Table3NavPropObject.TargetObject,
enumerable1 = t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject),
enumerable2 = t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject),
enumerable3 = t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject))
}
)
)
.ToListAsync();
The goal is to query all the referenced instances of TargetObject which is referenced accros ~ 10 different tables.
Currently it returns an IEnumerable where the anonymous object contains the properties singleObject, enumerable1, enumerable2, enumerable3. All those properties are of type TargetObject or IEnumerable.
Can I, and how, rewrite the query to not return anonymous objects but just an IEnumerable containing all the values?
For some reason the compiler won't let me iterate over the anonymous collection and flatten it manually.
This should do the trick if you want one array per t1e row.
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.Select
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
)
)
.ToListAsync();
If you want it completely flat, you'll want to switch that Select to a SelectMany().
var result = await dbContext.Table1DbSet
.Where(t1e => t1e.Id == id && t1e.Id2 == id2)
.SelectMany
(
t1e =>
t1e.Table2NavPropICollection.Select
(
t2e => new[] {t2e.Table3NavPropObject.TargetObject}.Concat(
t2e.Table3NavPropObject.Table4NavPropObject.Table5NavPropICollection.Select(t5e => t5e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table6NavPropObject.Table7NavPropICollection.Select(t7e => t7e.TargetObject)).Concat(
t2e.Table3NavPropObject.Table8NavPropICollection.SelectMany(t8e => t8e.Table9NavPropICollection.Select(t9e => t9e.TargetObject)))
)
)
.ToListAsync();
Is Add and/or Concat a possible solution?
PoC:
var a = new [] { 1,2,3 };
var result = new {
firstA = a.First(),
otherAs = a,
backwards = a.Reverse()
};
var final = new List<int>();
final.Add(result.firstA);
final.Concat(result.otherAs.Concat(result.backwards))
.Dump();

Last 6 Payments

I need to get the last six payments from a schema that consists of just
Contribution Id
DUE Date
Amount
The payments spread over 7 years and I need to get the most current last six payments only I thought this would do it it as it follows my sql
SELECT TOP 6 [ID]
,[customerInfo]
,[IVACODE]
,[Contribution]
,[DUE_DATE]
,[isActive]
,[isDeleted]
FROM [portal].[dbo].[tblPortalContributionSchedule]
where customerInfo='01F6B68B-6FC2-4F9D-B586-6934B8D6C979'
and DUE_DATE <='2016/09/26'
ORDER BY DUE_DATE DESC
Linq Version
List<tblPortalContributionSchedule> _contributions
= portalEntities.tblPortalContributionSchedules
.Where(a => a.customerInfo == _customerId
&& a.isDeleted == false
&& a.DUE_DATE <=Convert.ToDateTime("2016/09/26"))
.Take(6)
.OrderByDescending(o => o.DUE_DATE)
.ToList();
foreach (var contribution in _contributions)
{
AllPayments.Add(new Payments(contribution.ID, Convert.ToDecimal(contribution.Contribution), Convert.ToDateTime(contribution.DUE_DATE), false));
}
But its not producing the same results as per below
Sorry people i require the answer in linq i need to no is that the correct way of doing it i getting less than exepected
Edit 1
This is the query I have so far but I still am not getting the same results as my sql script
List<tblPortalContributionSchedule> _contributions =
portalEntities.tblPortalContributionSchedules.Where(a => a.customerInfo ==
_customerId && a.isDeleted == false && a.DUE_DATE
<=Convert.ToDateTime("2016/09/26")).OrderByDescending(o =>
o.DUE_DATE).Take(6).ToList();
Edit 2
To show the code that I showed in the video
public List<Payments> getAllPayments(Guid _customerId)
{
List<Payments> AllPayments = new List<Payments>();
List<tblPortalPayment> _payments = portalEntities.tblPortalPayments.Where(a => a.CustomerId == _customerId && a.isDeleted == false).ToList();
foreach (var payment in _payments)
{
AllPayments.Add(new Payments(payment.id, Convert.ToDecimal(payment.paymentDue), Convert.ToDateTime(payment.paymentDate), Convert.ToBoolean(payment.isinArrears)));
}
List<tblPortalContributionSchedule> _contributions = portalEntities.tblPortalContributionSchedules.Where(a => a.customerInfo == _customerId && a.isDeleted == false && a.DUE_DATE<= Convert.ToDateTime("2016/09/26")).OrderByDescending(o => o.DUE_DATE).Take(6).ToList();
foreach (var contribution in _contributions)
{
AllPayments.Add(new Payments(contribution.ID, Convert.ToDecimal(contribution.Contribution), Convert.ToDateTime(contribution.DUE_DATE), false));
}
var result = AllPayments.OrderByDescending(o => o.paymentDate).ToList();
return AllPayments.OrderByDescending(o => o.paymentDate).ToList();
}
You can try it as shown below and let us know the result.
var dueDateFilter = new DateTime(2016, 09, 26);
List<tblPortalContributionSchedule> _contributions =
portalEntities.tblPortalContributionSchedules
.Where(a => a.customerInfo == _customerId
&& a.isDeleted == false
&& a.DUE_DATE <= dueDateFilter)
.OrderByDescending(o => o.DUE_DATE)
.Take(6)
.ToList();
Try using this query
SELECT [ID],
[customerInfo],
[IVACODE],
[Contribution],
[DUE_DATE],
[isActive],
[isDeleted]
FROM [portal].[dbo].[tblPortalContributionSchedule]
where customerInfo='01F6B68B-6FC2-4F9D-B586-6934B8D6C979'
and ROWNUM <= 6
ORDER BY DUE_DATE DESC