What i am essentially trying to do is get all of the packages that have NOT been assigned a package location price for a specific location...
I have the following SQL:
SELECT * FROM Package
LEFT JOIN PackageLocationPrices ON Package.Id = PackageLocationPrices.PackageId
Where PackageLocationPrices.LocationId IS NULL
How can i convert this into Linq to entities?
I have tried something like this:
this.db.Packages.Include(p => p.PackageLocationPrices).Where(p => p.Id == p.PackageLocationPrices.????).ToList();
I am able to join package location prices but i am unable to get the properties of the packagelocationprices to do the SQL above? Below is my schema...The PackageLocationPrices.PackageId is a foreign key of Package.Id
Package Entitiy:
public partial class Package
{
public Package()
{
this.DiscountCodes = new HashSet<DiscountCode>();
this.PackageLocationPrices = new HashSet<PackageLocationPrice>();
this.Memberships = new HashSet<Membership>();
}
public int Id { get; set; }
public string Name { get; set; }
public int PackageOrder { get; set; }
public int PackageTypeId { get; set; }
public int PackagePeriodDays { get; set; }
public int PackagePeriodMonths { get; set; }
public int PackageSuspensionLimit { get; set; }
public int PackageSuspensionLimitIfAdminOverride { get; set; }
public int PackageSuspensionMinLength { get; set; }
public int PackageSuspensionMaxLength { get; set; }
public int PackageSuspensionsMaxLengthCombined { get; set; }
public int PackagePaymentHolidayLimit { get; set; }
public int PackagePaymentHolidayMinLength { get; set; }
public int PackagePaymentHolidayMaxLength { get; set; }
public int PackageVisitLimit { get; set; }
public bool PackageIsActive { get; set; }
public bool PackageIsReoccuring { get; set; }
public bool PackagePayInFull { get; set; }
public bool PackageIsSession { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime ModifiedDate { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public virtual AspNetUser AspNetUserCreatedBy { get; set; }
public virtual AspNetUser AspNetUserModifiedBy { get; set; }
public virtual ICollection<DiscountCode> DiscountCodes { get; set; }
public virtual PackageType PackageType { get; set; }
public virtual ICollection<PackageLocationPrice> PackageLocationPrices { get; set; }
public virtual ICollection<Membership> Memberships { get; set; }
}
Package Location Price Entity:
public partial class PackageLocationPrice
{
public int Id { get; set; }
public int LocationId { get; set; }
public int PackageId { get; set; }
public decimal MonthlyPrice { get; set; }
public decimal TotalPrice { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime ModifiedDate { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public virtual AspNetUser AspNetUserCreatedBy { get; set; }
public virtual AspNetUser AspNetUserModifiedBy { get; set; }
public virtual Location Location { get; set; }
public virtual Package Package { get; set; }
}
var result = (from p in Package
join q in PackageLocationPrices on p.Id equals q.PackageId into pq
from r in pq.DefaultIfEmpty()
select new {p, r}).ToList();
This should return something exactly like your SQL query.
I think you can create your query from another perspective:
var query=(from pl in db.PackageLocationPrices
where pl.LocationId == null
select pl.Package).ToList();
If you have disabled lazy loading then also need to use the Include extension method:
var query=(from pl in db.PackageLocationPrices.Include(p=>p.Package)
where pl.LocationId == null
select pl.Package).ToList();
Using method syntax would be this way:
var query=db.PackageLocationPrices.Include(p=>p.Package)
.Where(pl=>pl.LocationId == null)
.Select(pl=>pl.Package)
.ToList();
If you want as result both Package and PackageLocationPrice, then do this:
var query=db.PackageLocationPrices.Include(p=>p.Package)
.Where(pl=>pl.LocationId == null)
.ToList();
With this last query your are going to get a list of PackageLocationPrice, and if you want see the related Package for a givenPackageLocationPrice, you can use the Package navigation property.
Related
I have a LINQ expression that is not working correctly, when I see the SQL code generated the LEFT JOIN is not using the right foreign keys.
This is my Entity InventoryProcessAsset:
public class InventoryProcessAsset
{
[Key]
public Int64 InventoryProcessAssetId { get; set; }
public Int64 InventoryProcessId { get; set; }
public string AssetId { get; set; }
public string Epc { get; set; }
public int LocationId { get; set; }
public byte AssetStatus { get; set; }
public bool IsActive { get; set; }
public virtual Asset Asset { get; set; }
public virtual ICollection<AssetIncident> Incidents { get; set; }
}
This is my AssetIncident entity:
public class AssetIncident
{
[Key]
public long AssetIncidentId { get; set; }
public string AssetId { get; set; }
public DateTime IncidentDate { get; set; }
public byte IncidentType { get; set; }
public string? Notes { get; set; }
public Int64? InventoryProcessId { get; set; }
public virtual Asset Asset { get; set; }
public virtual InventoryProcessAsset ProcessAsset { get; set; }
}
In my modelBuilder I have the following relation:
modelBuilder.Entity<InventoryProcessAsset>()
.HasMany<AssetIncident>(x => x.Incidents)
.WithOne(g => g.ProcessAsset)
.HasForeignKey(x=> x.InventoryProcessId);
And finally this is my Linq expression:
var dbAssets = await _dbContext.InventoryProcessAssets
.Where(i => i.InventoryProcessId == processId)
.Include(a=> a.Incidents)
.ToListAsync();
When I see the SQL generated this is what I get:
So [t].[InventoryProcessAssetId] should be [t].[InventoryProcessId]
That's why is not bringing any data.
Any clue how to fix this?
I have two table like this -
public class Job
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime AddedTime { get; set; } = DateTime.Now;
public DateTime LastEdit { get; set; } = DateTime.Now;
public string Explanation { get; set; }
public string PhotoString { get; set; }
public bool isActive { get; set; } = true;
public int CompanyId { get; set; }
public Company Company { get; set; }
}
and company -
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Explanation { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string PhotoString { get; set; }
public bool isActive { get; set; } = true;
public int AppUserId { get; set; }
public AppUser AppUser { get; set; }
public List<Job> Jobs { get; set; }
}
I only want to get AppUserId from Company and all Jobs from every Company. I tried this and it gave me error.
using var context = new SocialWorldDbContext();
return await context.Jobs.Where(I => I.isActive == true && I.Company.isActive).Include(I=>I.Company.AppUserId).ToListAsync();
So my question is there any way I can get this data from parent?
Include adds whole entities to the output. To add just one property use Select, something like
context.Jobs
.Where(I => I.isActive == true && I.Company.isActive)
.Select(e => new {Job=e, CompanyAppUserId = e.Company.AppUserId})
.ToListAsync();
I have a table that i am attempting to query in order to create a menu. I am also querying the related tables to pair down result. I have a models project that contains all of my data models. In my Entities file I have
public IDbSet<Agent> Agents { get; set; }
public IDbSet<UsersLogin> UsersLogins { get; set; }
public IDbSet<Role> Roles { get; set; }
public IDbSet<UserRoleMapping> UserRoleMappings { get; set; }
public IDbSet<Qualifier> Qualifiers { get; set; }
public IDbSet<tblMenus> tblMenu { get; set; }
public IDbSet<tblUserMenuMapping> tblUserMenuMappings { get; set; }
public IDbSet<tblRoleMenuMapping> tblRoleMenuMappings { get; set; }
In my Interface i have ICollection<tblMenus> GetAllMenus();
Then i have my linq query which pares everything down and returns main menus and child menus.
public ICollection<tblMenus> GetAllMenus()
{
if (Global.CurrentProfile.UserID == 1)
{
return DataAccess.tblMenu.Where(m => !m.IsDeleted).ToList();
}
else
{
var UserInfo = GetUserInfo();
UserType = UserInfo.First().UserTypeID;
var childRoleMenus =
from menus in DataAccess.tblMenu
join roleMenus in DataAccess.tblRoleMenuMappings on menus.MenuID equals roleMenus.MenuID
join userRoles in DataAccess.UserRoleMappings on roleMenus.RoleID equals userRoles.RoleID
where userRoles.UserID == Global.CurrentProfile.UserID && !menus.IsDeleted
select menus;
var userChildMenus =
from menus in DataAccess.tblMenu
join userMenus in DataAccess.tblUserMenuMappings on menus.MenuID equals userMenus.MenuID
where userMenus.UserID == Global.CurrentProfile.UserID
select menus;
var childMenus = childRoleMenus.Union(userChildMenus).ToList();
However when i execute the query in my page it returns this error.
The specified type member 'MenuID' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported
Here are my models.
public class tblMenus : ModelBase
{
public int MenuID { get; set; }
public string MenuName { get; set; }
public string MenuLink { get; set; }
public Nullable<int> ParentID { get; set; }
public Nullable<bool> IsParent { get; set; }
public string IconImagePath { get; set; }
public Nullable<int> ApplicationID { get; set; }
public int CreatedBy { get; set; }
public System.DateTime CreatedOn { get; set; }
public string UpdatedBy { get; set; }
public Nullable<System.DateTime> UpdatedOn { get; set; }
public bool IsDeleted { get; set; }
public string ProcessedPage { get; set; }
public string MenuTarget { get; set; }
public Nullable<bool> IsEnabled { get; set; }
public string MenuCategory { get; set; }
public int MenuOrder { get; set; }
public virtual ICollection<tblRoleMenuMapping> tblRoleMenuMapping { get; set; }
public int RoleMenuID { get; set; }
public int RoleID { get; set; }
public int MenuID { get; set; }
public int CreatedBy { get; set; }
public System.DateTime CreatedOn { get; set; }
public Nullable<int> UpdatedBy { get; set; }
public Nullable<System.DateTime> UpdatedOn { get; set; }
public Nullable<bool> IsDeleted { get; set; }
public string ProcessedPage { get; set; }
public string PageAccessibility { get; set; }
public virtual ICollection<tblMenus> tblMenus { get; set; }
public virtual ICollection<Role> Role { get; set; }
public class tblUserMenuMapping : ModelBase
{
public int UserMenuID { get; set; }
public int UserID { get; set; }
public int MenuID { get; set; }
public Nullable<int> CreatedBy { get; set; }
public Nullable<System.DateTime> CreatedOn { get; set; }
public Nullable<int> UpdatedBy { get; set; }
public Nullable<System.DateTime> UpdatedOn { get; set; }
public bool IsDeleted { get; set; }
It's hard to say for sure without seeing the whole of both model classes and your database. Some things to check are:
Verify each respective 'MenuID' column exist in each underlying table. Because you aren't using mapping configurations, you need to make sure the column names follow the convention naming EF expects.
Verify their is a foreign key relationship between the two tables.
From a more general perspective, I would consider using configuration classes so your relationships are explicit and your model is more easily changed from the tables they map to.
Finally, you may see some clues by inspecting the SQL that EF has generated. Use the technique described in this post for any red flags (like EF is looking for a column that doesn't exist):
var result = from x in appEntities
where x.id = 32
select x;
var sql = ((System.Data.Objects.ObjectQuery)result).ToTraceString();
I have a linq query below that can't find 'DateTimeScheduled'
var yogaSpace = (from u in context.YogaSpaces
orderby u.Address.LocationPoints.Distance(myLocation)
where ((u.Address.LocationPoints.Distance(myLocation) <= 8047) && (u.Events.DateTimeScheduled >= classDate))
select u).ToPagedList(page, 10);
DateTimeScheduled is red and intellisense can't find anything inside u.Events almost like it doesn't exist. Intellisnse doesn't see the members inside Events.
Here is my YogaSpace and YogaSpaceEvent objects. I can compile everything fine if I remove the clause "&& (u.Events.DateTimeScheduled >= classDate)", furthermore I have data in my table for this object that I seeded to use for testing!
public class YogaSpace
{
public int YogaSpaceId { get; set; }
[Index(IsUnique = false)]
[Required]
[MaxLength(128)]
public string ApplicationUserRefId { get; set; }
public virtual YogaSpaceOverview Overview { get; set; }
public virtual YogaSpaceDetails Details { get; set; }
public virtual ICollection<YogaSpaceImage> Images { get; set; }
[Required]
public ListingComplete ImageCompleted { get; set; }
public byte[] Thumbnail { get; set; }
public virtual YogaSpaceListing Listing { get; set; }
public virtual YogaSpaceAddress Address { get; set; }
public virtual ICollection<YogaSpaceReview> Reviews { get; set; }
[Required]
public DateTime DateCreated { get; set; }
public virtual ICollection<YogaSpaceEvent> Events { get; set; }
[Required]
[Index]
public YogaSpaceStatus Status { get; set; }
[Required]
[Range(0, 4)]
public int StepsToList { get; set; }
[ForeignKey("ApplicationUserRefId")]
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class YogaSpaceEvent
{
public int YogaSpaceEventId { get; set; }
//public string Title { get; set; }
[Index]
//research more about clustered indexes to see if it's really needed here
//[Index(IsClustered = true, IsUnique = false)]
public DateTime DateTimeScheduled { get; set; }
public int AppointmentLength { get; set; }
public int StatusEnum { get; set; }
[Index]
public int YogaSpaceRefId { get; set; }
[ForeignKey("YogaSpaceRefId")]
public virtual YogaSpace YogaSpace { get; set; }
}
The property u.Events is a collection of events. Therefore it cannot have a single value for DateTimeScheduled, it has multiple values.
You need to select events that have DateTimeScheduled >= classDate first. Something like this:
var yogaSpace = (from u in context.YogaSpaces
orderby u.Address.LocationPoints.Distance(myLocation)
where ((u.Address.LocationPoints.Distance(myLocation) <= 8047)
&& (u.Events.Any(e => e.DateTimeScheduled >= classDate)))
select u).ToPagedList(page, 10);
The changed portion of the code u.Events.Any(e => e.DateTimeScheduled >= classDate) will now return a boolean true or false that indicates if any of the events are scheduled on or after the class date.
I have 2 models:
public partial class Movie
{
public Movie()
{
TimeTables = new HashSet<TimeTable>();
}
[Key]
public int MovieId { get; set; }
public string MovieName { get; set; }
public int MovieGenre { get; set; }
public string MoviePicture { get; set; }
public string MovieDescription { get; set; }
public string MovieShortText { get; set; }
public bool? MovieIs3d { get; set; }
public bool? MovieIsImax { get; set; }
public int MovieLanguage { get; set; }
public bool? MovieSubtitled { get; set; }
public int? MovieMinimalAge { get; set; }
public bool? MovieHasDrugs { get; set; }
public bool? MovieHasViolence { get; set; }
public bool? MovieHasSex { get; set; }
public bool? MovieHasSwearing { get; set; }
public bool? MovieIsScary { get; set; }
public bool? MovieHasDiscrimination { get; set; }
public string MovieTrailer { get; set; }
public int MovieLength { get; set; }
public int? Genre_GenreId { get; set; }
public int? Language_LanguageId { get; set; }
public virtual Genre Genre { get; set; }
public virtual Language Language { get; set; }
public virtual ICollection<TimeTable> TimeTables { get; set; }
}
And:
public partial class TimeTable
{
public TimeTable()
{
Reservations = new HashSet<Reservation>();
}
public int TimeTableId { get; set; }
public int MovieId { get; set; }
public int RoomId { get; set; }
public int SeatsAvaible { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public virtual Movie Movie { get; set; }
public virtual ICollection<Reservation> Reservations { get; set; }
public virtual Room Room { get; set; }
}
I want to show all the records from Movie which have one or more records in TimeTable and where StartDate.date == [given datetime].
With a simple query the movies are showing multiple times. I have tried a distinct() but that changes nothing.
Anybody here who have the solution?
Current query:
var times2 =
(from s in timetablerepo.TimeTables
orderby s.StartTime.TimeOfDay
where s.StartTime.Date == datetime.Date
select s).Distinct().ToList();
Why not start with movies first and filter by timetable:
var times = timetablerepo.Movies
.Where(m => m.TimeTables.Any(t => t.StartDate.Date == <yourdate>));