I have a query in SQL query as like below:
with pagedetail as
(
select
c.componentrefid, l.name, c.startdate,
ROW_NUMBER() over(PARTITION By c.componentrefid order by c.startdate desc) as rownumber
from
FM_componentTransaction as c
inner join
FM_LK_statusinfo as l on c.Statusinforefid = l.refid
inner join
fm_scriptinfo as s on s.Refid = c.ScriptRefId
where
s.CustomerInfoRefId = '85629125-7072-4EFE-9201-97E088E126C6'
)
select
pd.*
from
pagedetail pd
where
pd.rownumber = 1
I can get the output of this. Now my questions is how to implement this query using Entity Framework?
I know this is not a direct answer to your question, however one approach would be to create a stored procedure in SQL, and then just call the stored procedure in Entity Framework.
Code first:
How to call Stored Procedure in Entity Framework 6 (Code-First)?
Database First:
https://msdn.microsoft.com/en-us/data/gg699321.aspx
Assuming you have the following model:
public class ComponentTransaction
{
public Guid componentrefid { get; set; }
public string name { get; set; }
public DateTime startdate { get; set; }
public Guid Statusinforefid { get; set; }
public Guid ScriptRefId { get; set; }
}
public class Statusinfo
{
public Guid refid { get; set; }
}
public class Scriptinfo
{
public Guid refid { get; set; }
public Guid CustomerInfoRefId { get; set; }
}
The code can look like this:
Db db = new Db();
Guid customerInfoRefId = new Guid("85629125-7072-4EFE-9201-97E088E126C6");
var res = db.ComponentTransactions
.GroupBy(c => c.componentrefid)
.Select(g => g.OrderByDescending(c => c.startdate).First())
.Join(db.Statusinfos, c => c.Statusinforefid, l => l.refid, (c, l) => c)
.Join(db.Scriptinfos.Where(s => s.CustomerInfoRefId == customerInfoRefId),
c => c.ScriptRefId, s => s.refid, (c, s) => c);
Related
I want to return the Tags from the Tag table that are only found in the TagRecipe table. How can I do this?
var dataTags = await _context.Tags
.Include(tc => tc.TagCategory)
.ToListAsync();
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<TagRecipe> TagRecipes { get; set; }
public int TagCategoryID { get; set; }
public TagCategory TagCategory { get; set; }
}
public class TagRecipe
{
public int TagId { get; set; }
public int RecipeId { get; set; }
public Tag Tag { get; set; }
public Recipe Recipe { get; set; }
}
Thank you
Try this
var dataTags = await _context.TagRecipe
.Include(tc => tc.Tag.TagCategory)
.Select(i=> i.Tag)
.ToListAsync();
or you can use this syntax if you like it more
var dataTags = await _context.TagRecipe
.Include(t => t.Tag)
.ThenInclude(tc => tc.TagCategory)
.Select(i=> i.Tag)
.ToListAsync();
An alternative starting at table Tags using Join that will return a result without duplicates.
var dataTags = db.Tags
.Join(db.TagRecipes, tag => tag.Id, tagRecipe => tagRecipe.TagId, (tag, tagRecipe) => tag)
.Include(tag => tag.TagCategory)
.ToLookup(tag => tag.Id) // client-side from here
.Select(grouping => grouping.First()) // to make distinct
.ToList();
Will generate a straight-forward SQL
SELECT "t"."Id", "t"."Name", "t"."TagCategoryId", "t1"."Id", "t1"."Name"
FROM "Tags" AS "t"
INNER JOIN "TagRecipes" AS "t0" ON "t"."Id" = "t0"."TagId"
INNER JOIN "TagCategories" AS "t1" ON "t"."TagCategoryId" = "t1"."Id"
It is possible to use .Distinct in the above expression for removing duplicates instead of using grouping, but that will create a more complex SQL.
Table TagRecipes seems to be a join table in a many-to-many between table Tags and table Recipes. The latter is not included in the question, but I added it during my tests.
Please note that in EF Core 5, many-to-many relations may be created without an entity class for the join table.
I have structure like this:
public class OuterResource
{
public int Id { get; set; }
[Nested]
public List<InnerResource> InnerResources { get; set; }
}
public class InnerResource
{
public int Id { get; set; }
public int OuterResourceId { get; set; }
public int Value { get; set; }
}
Inner records are stored as lists inside outer records. I want to query inner records, giving specified outer resource id and value to filter inner records.
How to do it in C# Nest? Can't figure it out from documentation.
Please try this.
objforOuterResource.InnerResources.Where(x => x.Id == 5);
.Query<OuterResource>.Nested(n => n
.Path(p => p.InnerResources)
.Query(qq => qq
.Terms(t => t.Fields(fi => fi.InnerResources.First().OuterResourceId ).Terms(value))
)
)
Should work. Note the .First is applied to all the array (=list)
I am new to Linq. For the learning perspective, I am trying to convert this following sql query to linq query. However, this gives me nothing. No error message or anything. The sql query gives me the table but linq doesn't give me values.
The SQL query:
SELECT
Members.FirstName,
Members.LastName,
PhoneScreens.BaselineEligibility
FROM
Members INNER JOIN PhoneScreens ON Members.Id = PhoneScreens.MemberId
WHERE PhoneScreens.BaselineEligibility = 'eligible'
And the Linq query is:
context.Members
.Include(p => p.PhoneScreens)
.Where(y => y.PhoneScreens.BaselineEligibility == "eligible")
.ToListAsync();
EDIT:
Here are the classes:
public class Member
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<PhoneScreen> PhoneScreens { get; set; }
public Member()
{
PhoneScreens = new Collection<PhoneScreen>();
}
}
public class PhoneScreen
{
public string BaselineEligibility { get; set; }
public Member Member { get; set; }
public int MemberId { get; set; }
}
I would appreciate any help.
This will do the work:
context.Members
.Include(c => c.PhoneScreens)
.Where(m => m.PhoneScreens.Any(i => i.BaselineEligibility == "eligible"))
I'm having a problem with my query in NHibernate With DetachedCriteria (or using Session QueryOver). I need to get only a few columns from each table, like the classes as follow:
public class PanelaCorrida : BaseEntity
{
public virtual Int64? CodCorrida { get; set; }
public virtual Int64 NumLocal { get; set; }
public virtual Boolean IdcInspecionada { get; set; }
public virtual String Sigla { get; set; }
public virtual String Rota { get; set; }
public virtual Local Local { get; set; }
public virtual Panela Panela { get; set; }
}
public class Panela : BaseEntity
{
public Panela()
{
this.Local = new Local();
this.PanelaCorridas = new List<PanelaCorrida>();
}
public virtual Int32 Numero { get; set; }
public virtual Boolean IdcAtiva { get; set; }
public virtual Int16 Status { get; set; }
public virtual ICollection<PanelaCorrida> PanelaCorridas { get; set; }
public virtual Local Local { get; set; }
#endregion
}
public class Local : BaseEntity
{
public Local()
{
this.PanelaCorridas = new List<PanelaCorrida>();
this.Panelas = new List<Panela>();
}
#region Property
public virtual Int32 IdLocal { get; set; }
public virtual Int32 AreaLocal { get; set; }
public virtual String Descricao { get; set; }
public virtual String Codigo { get; set; }
#endregion
}
Basically, the Entity 'Panela' is the Mother of 'PanelaCorrida' (Each Panela can have multiple PanelaCorrida's) but a 'PanelaCorrida' can be in one Local. But one local can have multiple PanelaCorrida's as well. It's basically, this relationship:
Panela 1 - N PanelaCorrida
Local 1 - N Panela
Local 1 - N PanelaCorrida
For this query, i need to get the Last PanelaCorrida of the db, but i need the info of Panela and Local as well.
So far, i can get all data using this NHibernate query:
To get all id's of 'panela' which is active:
var panelaIdList = Session.QueryOver<Panela>()
.Select(c => c.Id)
.Where(c => c.IdcAtiva == true)
.List<Int64>();
To get all last id's of 'PanelaCorrida' which is active (and the last PanelaCorrida generated):
var corridaPanelaIdList = Session.QueryOver<PanelaCorrida>()
.Select(
Projections.Max<PanelaCorrida>(x => x.Id),
Projections.Group<PanelaCorrida>(x => x.Panela)
)
.Where(p => p.Panela.IsIn(panelaIdList.ToArray()))
.List<Object[]>();
Now, to get the result with all info of all those tables:
With DetachedCriteria:
criteria = DetachedCriteria.For<PanelaCorrida>()
.CreateAlias("Local", "L")
.CreateAlias("Panela", "P")
.Add(Restrictions.In("Id", corridaPanelaIdList.Select(x => x[0]).ToArray()));
With Session QueryOver:
var corridas = Session.QueryOver<PanelaCorrida>()
.Where(p => p.Id.IsIn(corridaPanelaIdList.Select(x => x[0]).ToArray()))
.List<PanelaCorrida>();
But the problem is, i need only a few columns of each Table. With NHibernate i've tried with Projections, and with QueryOver, i've tried with SelectList, but each time they generate a error (could not found the property of ...) or they do not populate the entities in result.
How i could achieve this?
Note: This is my query in first place (in SQL):
select cd.num_panela_corrida, cd.num_panela, p.numero, l.num_local from scp_panela_corrida cd
inner join scp_panela p on p.num_panela = cd.num_panela
inner join scp_local l on l.num_local = cd.num_local and cd.num_panela_corrida
in (
select
max( c.num_panela_corrida) as num_panela_corrida
from
scp_panela_corrida c
inner join
scp_panela p on p.num_panela = c.num_panela
and p.num_panela in (
select
num_panela
from
scp_panela
where
idc_ativa = 1
) group by c.num_panela ) order by cd.num_panela_corrida desc
But the client don't want to use a Stored Procedure or HQL.
Any help is welcome.
Resolved with the following code (provided with the link of Radim Kohler).
Radim, if you want, please answer this question with the provided link and i'll accept it as the answer. Thanks for your help.
Panela panela = null;
Local local = null;
var query = session.QueryOver<PanelaCorrida>()
.JoinAlias(c => c.Panela, () => panela)
.Where (c => c.Id.IsIn(corridaPanelaIdList.ToArray()))
.SelectList(list => list
.Select(c => c.Id))
.Select(c => c.CodCorrida)
.Select(Projections.Property(() => panela.Id).As("Panela.Id"))
.Select(Projections.Property(() => panela.IdcAtiva).As("Panela.IdcAtiva"))
.TransformUsing(Transformers.AliasToBean(typeof(PanelaCorrida)));
Don't know if is the best approach, but it worked. We will analyze best approaches using QueryOver/DetachedCriteria, but for now, this works great.
Note: I've removed some columns, just to explain how it worked.
Thanks again.
I'm battling to retrieve a single Model/Entity using EntityFramework and Linq.
I have a Business with Members, I'm trying to retrieve the users' business based on the BusinessMembers table/entity.
I have the following entities/models:
public partial class Business
{
public Business()
{
BusinessMembers = new HashSet<BusinessMember>();
}
public int ID { get; set; }
public int ID_BusinessStatus { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Phone { get; set; }
public virtual BusinessStatus BusinessStatus { get; set; }
public virtual ICollection<BusinessMember> BusinessMembers { get; set; }
}
and
public partial class BusinessStatus
{
public BusinessStatus()
{
Businesses = new HashSet<Business>();
}
public int ID { get; set; }
[Required]
[StringLength(3)]
public string Code { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<Business> Businesses { get; set; }
}
I then have the following method to return a Single Business Instance:
public Business GetBusinessForUser(string userId)
{
using (var db = new MyContext(_connectionString))
{
var q =
from b in db.Businesses
join bm in db.BusinessMembers on b.ID equals bm.ID_Business
where bm.UserId == userId
select b;
return q.FirstOrDefault();
}
}
Problem I'm having is I want to 'Include' the BusinessStatus for that single Business entity and don't know how to do this.
I need to be able to do:
Business businessEntity = _dataServices.GetBusinessForUser(userId);
if (businessEntity.BusinessStatus.Code == "ACT")
{
// Whatever
}
First, add this to the list of usings
using System.Data.Entity;
Then you can use the .Include() method to load additional children in your query
public Business GetBusinessForUser(string userId)
{
using (var db = new MyContext(_connectionString))
{
var q =
(from b in db.Businesses
join bm in db.BusinessMembers on b.ID equals bm.ID_Business
where bm.UserId == userId
select b).Include(business => business.BusinessStatus);
return q.FirstOrDefault();
}
}
I would also avoid using the join method explicitly. If your model has correct relationships (e.g. foreign keys), you should be able to just do this:
var q = db.Businesses
.Where(b => b.BusinessMembers.Any(bm => bm.UserId == userId))
.Include(b => b.BusinessStatus);
return q.FirstOrDefault();
or even
var q = db.BusinessMembers
.Where(bm => bm.UserId == userId)
.Select(bm => bm.Business)
.Include(b => b.BusinessStatus);