i have entity classes below,i want to a query like sql,how is that posssible with entity framework??
select * from SiteUsers su
inner join SiteUserRoles sur on su.Id=sur.SiteUserId
inner join SiteRoleActions sra on sur.SiteRoleId = sra.SiteRoleId
inner join SiteActions sa on sa.Id = sra.SiteActionId
where su.Id=1 and sa.ParentId=189
public class SiteRole
{
public SiteRole()
{
this.SiteActions = new HashSet<SiteAction>();
this.SiteUser = new HashSet<SiteUser>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<SiteAction> SiteActions { get; set; }
public virtual ICollection<SiteUser> SiteUser { get; set; }
}
public partial class SiteUser
{
public SiteUser()
{
this.SiteRoles = new HashSet<SiteRole>();
}
public int Id { get; set; }
public string Email { get; set; }
public string UserPassword { get; set; }
public string UserName { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public Nullable<System.DateTime> DateCreated { get; set; }
public virtual ICollection<SiteRole> SiteRoles { get; set; }
}
public partial class SiteAction
{
public SiteAction()
{
this.Childs = new HashSet<SiteAction>();
this.SiteRoles = new HashSet<SiteRole>();
}
public int Id { get; set; }
public string Name { get; set; }
public string ImagePath { get; set; }
public string ActionName { get; set; }
public string ControllerName { get; set; }
public Nullable<int> ParentId { get; set; }
public Nullable<int> Type { get; set; }
public virtual ICollection<SiteAction> Childs { get; set; }
public virtual SiteAction Parent { get; set; }
public virtual ICollection<SiteRole> SiteRoles { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<SiteUser>().HasMany<SiteRole>(r => r.SiteRoles).WithMany(u => u.SiteUser).Map(m =>
{
m.ToTable("SiteUserRoles");
m.MapLeftKey("SiteUserId");
m.MapRightKey("SiteRoleId");
});
modelBuilder.Entity<SiteRole>().HasMany<SiteAction>(r => r.SiteActions).WithMany(u => u.SiteRoles).Map(m =>
{
m.ToTable("SiteRoleActions");
m.MapLeftKey("SiteRoleId");
m.MapRightKey("SiteActionId");
});
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
Since you don't have SiteUserRoles and SiteRoleActions as entities but only as join tables (if I read you well), you should use the navigation properties in stead of joining. Something like:
conext.SiteUsers.Where(su => su.id == 1
&& su.SiteRoles.SelectMany(sr => sr.SiteActions)
.Any(sa => sa.ParentId == 189 )
(Not syntax checked).
var result= (from su in SiteUsers
join sur in SiteUserRoles
on su.Id=sur.SiteUserId
join sra in SiteRoleActions
on sur.SiteRoleId = sra.SiteRoleId
join sa in SiteActions
on sra.SiteActionId=sa.Id
where su.Id=1 and sa.ParentId=189
select su).ToList();
Hope this will help . result will be a list of type SiteUsers.
Related
I have the following Linq statement that is currently not working.
var result = ClientDATARepository.AllIncluding(c => c.Jobs, c => c.ClientNotes, c => c.Suburb).Where(x => x.Id == id).Select(fetchedClient =>
new ClientDetailsDto {
Id = fetchedClient.Id,
ClientNo = fetchedClient.ClientNo,
Company = fetchedClient.Company,
IsWarrantyCompany = fetchedClient.IsWarrantyCompany,
CompanyName = fetchedClient.CompanyName,
ClientFirstName = fetchedClient.ClientFirstName,
ClientLastName = fetchedClient.ClientLastName,
MobilePhone = fetchedClient.MobilePhone,
DeActivated = fetchedClient.DateDeActivated.HasValue ? "true" : "false",
CreatedOn = EF.Property<DateTime>(fetchedClient, "CreatedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ModifiedOn = EF.Property<DateTime>(fetchedClient, "ModifiedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ClientNotes = fetchedClient.ClientNotes.Select(fetchedClientNote =>
new ClientNoteDto {
id = fetchedClientNote.Id,
Details = fetchedClientNote.Details,
}) as IQueryable<ClientNoteDto>
The initial method ClientDATARepository.AllIncluding is from the repository and is suppose to return the full details of a client:
public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = _context.Set<T>();
return includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
}
Which should include all associated entities requested... which works to obtain a client however no ClientNotes are returned yet there are clientNotes in the database for the selected client.
The Dto I am trying to fill in is a follows:
public class ClientDetailsDto
{
public ClientDetailsDto()
{
}
[Key]
public int Id { get; set; }
public string ClientNo { get; set; }
public bool Company { get; set; }
public bool IsWarrantyCompany { set; get; }
public string CompanyName { get; set; }
public string ClientFirstName { get; set; }
public string ClientLastName { get; set; }
public string MobilePhone { get; set; }
public string DeActivated { get; set; }
public string CreatedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public int SuburbId { get; set; }
public AddressDto Address { get; set; }
public IQueryable<ClientJobDto> ClientJobs { get; set; }
public IQueryable<ClientNoteDto> ClientNotes { get; set; }
}
ClientNoteDto is also presented for completeness:
public class ClientNoteDto
{
[Key]
public int id { get; set; }
public string Details { get; set; }
public string NoteType { get; set; }
public string CreatedOnDate { get; set; }
public string CreatedOnTime { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOnDate { get; set; }
public string ModifiedOnTime { get; set; }
public string ModifiedBy { get; set; }
}
How do I get the IQueryable statement to return all the notes for this client as part of the result?
I'm getting data from an Oracle database and creating an API for internal use. Some of the classes are (shortened for brevity):
CustomerOrderTab
Public partial class CustomerOrderTab
Public string OrderNo { get; set; }
[ForeignKey("CustomerMV")]
public string CustomerNo { get; set; }
public List<CustomerOrderLineTab> CustomerOrderLines { get; set; }
public List<CustomerOrderChargeTab> CustomerOrderCharge { get; set; }
public List<ShipmentOrderLineTab> ShipmentOrderLines { get; set; }
public CustomerMV CustomerMV { get; set; }
CustomerOrderDTO
Public class OrderDTO
public string OrderNo { get; set; }
public string CustomerName { get; set; }
public List<OrderLinesDTO> OrderLines { get; set; }
public List<OrderChargesDTO> OrderCharges { get; set; }
public List<ShipmentOrderLinesDTO> ShipmentOrderLines { get; set; }
ShipmentOrderLineTab
public partial class ShipmentOrderLineTab
public decimal ShipmentId { get; set; }
[ForeignKey("CustomerOrderTab")]
public string OrderNo { get; set; }
public ShipmentTab Shipment { get; set; }
ShipmentOrderLineDTO
public class ShipmentOrderLinesDTO
public decimal ShipmentId { get; set; }
public string OrderNo { get; set; }
public ShipmentTab MyShipment { get; set; }
ShipmentTab
public partial class ShipmentTab
[ForeignKey("ShipmentOrderLineTab")]
public decimal ShipmentId { get; set; }
public string ShipperAddress1 { get; set; }
public string ShipperAddress2 { get; set; }
public List<ShipmentHandlingUnitTab> ShipmentHandlingUnits { get; set; }
ShipmentDTO
public class ShipmentDTO
public decimal ShipmentId { get; set; }
public string ShipViaCode { get; set; }
public string ShipmentPayer { get; set; }
public List<ShipmentHandlingUnitDTO> ShipmentHandlingUnitDTOs { get; set; }
This Works:
var orderLines = from o in _context.CustomerOrderTab
.Where(o => o.OrderNo == orderno)
select new OrderDTO()
{
OrderNo = o.OrderNo,
CustomerName = o.CustomerMV.CustomerName,
This is a child of the order ShipmentOrderLines = o.ShipmentOrderLines
This works .Select(ob => new ShipmentOrderLinesDTO
{
ShipmentId = ob.ShipmentId,
OrderNo = ob.OrderNo,
MyShipment = ob.Shipment
Adding this does not work .Select(y => new ShipmentDTO
The error says that ShipmentTab
Doesn’t have a definition for Select {
}
}).ToList()
Shipment is a child of ShipmentOrderLine (there will only be one shipment per line)
ShipmentOrderLine is a child of CustomerOrder (there can be many lines per order)
I think the problem is that there is only one shipment per line but I've tried lots of things and can't get it to map to my DTO.
Fix your model:
ShipmentOrderLineDTO
public class ShipmentOrderLinesDTO
public decimal ShipmentId { get; set; }
public string OrderNo { get; set; }
public ShipmentDTO MyShipment { get; set; }
Select is only used to project a collection. For non-collections, you just create a new object...
var orderLines = _context.CustomerOrderTab
.Where(o => o.OrderNo == orderno)
.Select(o => new OrderDTO {
OrderNo = o.OrderNo,
CustomerName = o.CustomerMV.CustomerName,
ShipmentOrderLines = o.ShipmentOrderLines
.Select(ob => new ShipmentOrderLinesDTO {
ShipmentId = ob.ShipmentId,
OrderNo = ob.OrderNo,
MyShipment = new ShipmentDTO {
ShipmentId = ob.Shipment.ShipmentId,
...
ShipmentHandlingUnits = ob.Shipment.ShipmentHandlingUnits
.Select(shu=> new ShipmentHandlingUnitDTO {
...
}).ToList()
}
}
}).ToList()
Now with that all said, I typically have mapping extension methods on my data model classes, which allow things like this:
var orderLines = _context.CustomerOrderTab
.Where(o=>o.OrderNo == orderno)
.Select(o=> o.ToDto());
Example class:
public static class CustomerOrderTabExtensions {
public static CustomerOrderDto ToDto(this CustomerOrderTab cot) {
return new CustomerOrderDto {
OrderNo = cot.OrderNo,
...
OrderLines = cot.CustomerOrderLines
.Select(col=>col.ToDto())
.ToList()
}
}
}
Or use Automapper.
I have a Model:
public class Transaction
{
public Guid ID { get; set; }
public Guid CategoryID { get; set; }
public List<Guid> Tags { get; set; }
}
public class Category
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
public class Tag
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
I have a ModelRepository of Model objects. I have VieModels:
public class TransactionViewModel
{
public Guid ID { get; set; }
public CategoryViewModel Category { get; set; }
public List<TagViewModel> Tags { get; set; }
}
public class CategoryViewModel
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
public class TagViewModel
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
Now I need to make List<TransactionViewModel> from List <Transaction> using linq. How did I:
VM.Categories = ModelRepository.Categories.Select(p => new CategoryViewModel(p)));
VM.Tags = ModelRepository.Tags.Select(p => new TagViewModel(p)));
var trans = from t in ModelRepository.Transactions
join c in VM.Categories on t.CategoryID equals c.ID
select new TransactionViewModel()
{
...,
Category = c
};
VM.Transactions = trans.ToList();
Now when I change any CategoryViewModel in VM.Categories, I immediately get changes for all TransactionViewModel.Category in VM.Transactions. Question - how do I fill TransactionViewModel.Tags? Preferably with LINQ. And it's mandatory that when changing any TagViewModel in VM.Tags, I immediately get changes for all TransactionViewModel.Tags in VM.Transactions.
Below is the Entity class
public partial class TestPlanViewModel
{
public TestPlanViewModel()
{
this.TestPlanTestPoints = new List<TestPlanTestPoint>();
}
public int TestPlanId { get; set; }
public string TestPlanName { get; set; }
public virtual IList<TestPlanTestPoint> TestPlanTestPoints { get; set; }
}
public class TestPlanTestPoint
{
public int OrganizationId { get; set; }
public int TestPlanId { get; set; }
public string TestPlanName { get; set; }
public int TestPlanVersion { get; set; }
public int TestPointId { get; set; }
public string TestPointName { get; set; }
}
I need to write a query where I need to get the collections from the dbContext like,
var query = (from tpm in TestPlanMaster
join tptp in TestPlanTestPoint on tpm.TestPlanId equals tptp.TestPlanId
join tmm in TestMethodMaster on tptp.TestMethodId equals tmm.TestMethodId
join tpma in TestPointMaster on tptp.TestPointId equals tpma.TestPointId
select new
{
//Plan Details
tpm.TestPlanId,
tpm.TestPlanName,
}).ToList().Select(x => new Entities.CustomEntities.TestPlanViewModel ====> Custom Entity
{
TestPlanId = x.TestPlanId,
TestPlanName = x.TestPlanName,
TestPlanTestPoints = ?????? ==> how to fill this collection
});
As shown above the TestPlanTestPoints is the IList collection object. I need to populate the data with the values from TestPlanTestPoint table.
Any suggestions?
Model
TestPlan
public partial class TestPlanMaster
{
[DataMember]
public int TestPlanId { get; set; }
[DataMember]
public short TestPlanVersion { get; set; }
[DataMember]
public int OrganizationId { get; set; }
[DataMember]
public short TestPlanTypeId { get; set; }
[DataMember]
public string TestPlanName { get; set; }
}
TestPlanTestPointMapping Model
public partial class TestPlanTestPointMapping
{
[DataMember]
public int OrganizationId { get; set; }
[DataMember]
public int TestPlanId { get; set; }
[DataMember]
public short TestPlanVersion { get; set; }
[DataMember]
public int TestPointId { get; set; }
}
You are thinking too much sql, think more linq. You want to select "tpm" items, so just write a select of those and select the new TestPlanViewModel and fill its properties and navigational properties.
I'm assuming you have a TestPlanTestPoints navigational property in your TestPlanMaster.
var q = (from tpm in TestPlanMaster
select new TestPlanViewModel
{
TestPlanId = tpm.TestPlanId,
TestPlanName = tpm.TestPlanName,
TestPlanPoints = TestPlanTestPoint.Where(pr => tpm.TestPlanId == pr.TestPlanId).Select(tptp => new TestPlanTestPoint()
{
// Fill properties here
}
}).ToList();
i want to User entity with Action's of Site Role's but point is ExtraAction entity,Action data will be filter by ExtraAction entity,
in ExtraAction entity:
if Type property == 1 this to be UNION to Action entity
if Type property == 0 this to be EXCEPT to Action entity
public class User
{
public int Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public ICollection<SiteRole> SiteRoles { get; set; }
public ICollection<ExtraAction> ExtraActions { get; set; }
}
public class SiteRole
{
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<Action> Actions { get; set; }
public virtual ICollection<User> User { get; set; }
}
public class ExtraAction
{
public int Id { get; set; }
public int UserId { get; set; }
public int ActionId { get; set; }
public byte Type { get; set; }
public virtual Action Action { get; set; }
public virtual User User { get; set; }
}
public class Action
{
public int Id { get; set; }
public string Name { get; set; }
public string ActionName { get; set; }
public string ControllerName { get; set; }
public ICollection<SiteRole> SiteRoles { get; set; }
public virtual ICollection<ExtraAction> ExtraActions { get; set; }
}
finally my solution is below
var list = dbContext.Actions.Where(u =>
u.Roles.SelectMany(r => r.User).Any(su => su.Id == Id)).Select(row => new { Action = row }).
Union(dbContext.ExtraActions.Where(suea => suea.Type == 1 && suea.UserId == Id).Select(row => new { Action = row.Action })).
Except(dbContext.ExtraActions.Where(suea => suea.Type == 0 && suea.UserId == Id).Select(row => new { Action = row.Action })).ToList();