EF-Core query but value missing, even it show in database - entity-framework

here is the simple query code...
var order = await _context.ProductOrders
.FirstOrDefaultAsync(x => x.Id == orderId.ToInt());
This is the entity of ProdictOrders
public class ProductOrder
{
public int Id { get; set; }
public int MovieTicketEnrollmentId { get; set; }
public string ProductOrderStatusCode { get; set; }
public int? InvoiceId { get; set; }
public DateTime CreateDate { get; set; }
public string CreateBy { get; set; }
public DateTime? UpdateDate { get; set; }
public string UpdateBy { get; set; }
/**
* Navigation Property
*/
public MovieTicketEnrollment MovieTicketEnrollment { get; set; }
public ProductOrderStatus ProductOrderStatus { get; set; }
public ICollection<ProductOrderItem> ProductOrderItems { get; set; }
public Invoice Invoice { get; set; }
}
This data in the database
And what I got after executing query command above... what's just happening here?
MovieTicketEnrollmentId should equal to 1

Related

Can anyone give me a solution how we will merge the two different repositories i.e.. two tables in a same database we want to use a Linq query

Working code - but it is not getting output what is the wrong in this code:
var result = _favouriteProjectRepository.Entity()
.Where(x => x.UserId == userId)
.Select(x => new FavouriteProject
{
ProjectId = x.ProjectId,
}).ToList();
var resultset = await _projectrepository.Entity()
.Where(x => (filters.FiscalYear == null ||
filters.FiscalYear.Contains(Convert.ToInt32(x.ContractNo.ToString().Substring(0, 2)))) &&
(filters.IsFavourite == false &&
result.Contains(x.Id).ToString()))
.Select(x => new Tests
{
Id = x.Id,
Name = x.Name,
AdvertisementStatusId = x.AdvertisementStatusId,
CreatedOn = x.CreatedOn,
ContractNo = x.ContractN0,
})
.OrderBy(x => x.Name)
.ToListAsync();
Models:-
public class FavouriteProject
{
public int ProjectId { get; set; }
public string UserId { get; set; }
public virtual Project Project { get; set; }
}
public class Tests
{
public int Id { get; set; }
public string Name { get; set; }
public int? ContractNo { get; set; }
public int? AdvertisementStatusId { get; set; }
public DateTime? CreatedOn { get; set; }
public virtual ICollection<FavouriteCompany> FavouriteCompany { get; set; }
}
**filters**
public class ProjectFilters
{
public List<int> FiscalYear { get; set; }
public bool IsFavourite { get; set; }
}
**Project Model**
public class Project
{
public int Id { get; set; }
public string ProcurmentNo { get; set; }
public int? ContractNo { get; set; }
public int? ProjectSizeId { get; set; }
public int? SelectionProcedureId { get; set; }
public int? ResponseRequestedId { get; set; }
public int? AdvertisementStatusId { get; set; }
public int? NoOfPages { get; set; }
public string PreQualificationRequirements { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public string MultilineDescription { get; set; }
public string BridgDesignWorkType { get; set; }
public string DbeMbeRequirements { get; set; }
public string SpecialNote { get; set; }
public decimal? BudgetAmount { get; set; }
public decimal? EstimatedContractAmount { get; set; }
public decimal? MaxumumContractAmount { get; set; }
public bool? IsMultipleContracts { get; set; }
public string ProposedScopeLoc { get; set; }
public string BondingRequirements { get; set; }
public string TechQuestionsAddressedTo { get; set; }
public int Status { get; set; }
public int? DistrictId { get; set; }
public DateTime? CreatedOn { get; set; }
public string ResponseEmail { get; set; }
public string ViewRFP { get; set; }
public string AdditionalInformation { get; set; }
public string LowBidDesign { get; set; }
public string AdminNote { get; set; }
public string MeetingLocationNotes { get; set; }
public string FdotKey { get; set; }
//public DateTime? EventDate { get; set; }
public bool IsUpdatesLocked { get; set; }
public bool? BdiProjectIndicator { get; set; }
public string LiabilityInsurance { get; set; }
public string ProjectThreshold { get; set; }
public int NumberOfContracts { get; set; }
public int? RelatedProjectCount { get; set; }
public string AdvertisementSpecialNotes { get; set; }
public string FMNSpecialNotes { get; set; }
public virtual ProjectSize ProjectSize { get; set; }
public virtual SelectionProcedure SelectionProcedure { get; set; }
public virtual ResponseRequested ResponseRequested { get; set; }
public virtual AdvertisementStatus AdvertisementStatus { get; set; }
public virtual District District { get; set; }
public virtual ICollection<ProjectEvent> ProjectEvents { get; set; }
public virtual ICollection<FinancialManagementNumber> FinancialManagementNumbers { get; set; }
public virtual ICollection<ProjectWorkGroup> ProjectWorkGroups { get; set; }
public virtual ICollection<ScrapedLink> ScrapedLinks { get; set; }
public virtual ICollection<ProjectStandardNote> ProjectStandardNotes { get; set; }
public virtual ICollection<FtpFileProject> FtpFileProjects { get; set; }
public virtual ICollection<CompanyProject> CompanyProjects { get; set; }
public virtual ICollection<ContactProject> ContactProjects { get; set; }
public virtual ICollection<ProjectUnderUtilizedWorkGroup> ProjectUnderUtilizedWorkGroups { get; set; }
public virtual ICollection<WorkProgram> WorkPrograms { get; set; }
[NotMapped]
public virtual ICollection<ScrapedProjectModel> ScrapedProjects { get; set; }
// public virtual FavouriteProject FavouriteProject { get; set; }
Can anyone give me simplified query to call both in single request?
And I have added my models and filters you can go through it I have used only one filters and the model of project because in that class only I have mentioned
Try the following query:
var query = _projectrepository.Entity().AsQueryable();
if (filters.FiscalYear?.Count > 0)
{
query = query.Where(x => filters.FiscalYear.Contains(Convert.ToInt32(x.ContractNo.ToString().Substring(0, 2))));
}
if (filters.IsFavourite)
{
var favouriteProjects = _favouriteProjectRepository.Entity()
.Where(x => x.UserId == userId);
query =
from p in query
join f in favouriteProjects on p.Id equals f.ProjectId
select p;
}
var resultset = await query
.Select(x => new Tests
{
Id = x.Id,
Name = x.Name,
AdvertisementStatusId = x.AdvertisementStatusId,
CreatedOn = x.CreatedOn,
ContractNo = x.ContractN0,
})
.OrderBy(x => x.Name)
.ToListAsync();

EF Lambda How to make projection for GroupJoin

I am trying to query EF models. (GameBank and GameCouponBank) How can I make a projection for left outer join (GoupJoin)?
Can I make projection for Coupons?
Here is my query
var gameBankResult = context.GameBanks.GroupJoin(context.GameCouponBanks, g => g.GameBankID, gc => gc.GameBankID,
(g,gc) => new {
g.quantity,
g.currency,
g.initiationResultCode,
g.productCode,
g.productDescription,
g.referenceId,
g.responseDateTime,
g.unitPrice,
g.totalPrice,
Coupons = gc
})
.Where(g => g.productCode == initiate.productCode)
.Select(s => s);
Here is models:
public class GameBank
{
public int GameBankID { get; set; }
public string referenceId { get; set; }
public string productCode { get; set; }
public int quantity { get; set; }
public string version { get; set; }
public DateTime? requestDateTime { get; set; } = DateTime.Now;
public int? customerID { get; set; }
public string password { get; set; }
public DateTime? responseDateTime { get; set; } = DateTime.Now;
public string initiationResultCode { get; set; }
public string companyToken { get; set; }
public int used { get; set; }
public string productDescription { get; set; }
public string currency { get; set; }
public double unitPrice { get; set; }
public double totalPrice { get; set; }
public virtual List<GameCouponBank> coupons { get; set; }
}
public class GameCouponBank
{
public int Id { get; set; }
public int GameBankID { get; set; }
public DateTime? expiryDate { get; set; }
public string Serial { get; set; }
public string Pin { get; set; }
}
You don't need to use GroupJoin explicitly. You can simply project your query as follows:
var gameBankResult = context.GameBanks.Where(g => g.productCode == initiate.productCode)
.Select(g => new {
g.quantity,
g.currency,
g.initiationResultCode,
g.productCode,
g.productDescription,
g.referenceId,
g.responseDateTime,
g.unitPrice,
g.totalPrice,
Coupons = g.coupons.Select(c => new {c.Id, c.GameBankID,...}).ToList() //<-- Here is the projection for coupons
}).FirstOrDefault(); // I assume you are returning single entity, if not then use `.ToList()` instead of `.FirstOrDefault()`

How to get EF.core to use LEFT JOINs instead of INNER JOINs

I'm trying to include foreign-key details as part of my query.
How can I get EF.core to use LEFT JOINs instead of INNER JOINs?
public class Offence
{
[Key]
public Int32 offence_id { get; set; }
public Int32 guard_id { get; set; }
public Int32 penalty_id { get; set; }
public DateTime? dt_recorded { get; set; }
public Int32 salary_id { get; set; }
public Decimal? amount { get; set; }
public String status { get; set; }
public Int32 site_id { get; set; }
public Guard Guard { get; set; }
public Salary Salary { get; set; }
public Site Site { get; set; }
public Penalty Penalty { get; set; }
public DateTime? last_modified { get; set; }
public int? last_modified_by { get; set; }
}
In Controller GetList
var offences = db.Offences
.Include(e => e.Guard)
.Include(e => e.Penalty)
.Include(e => e.Site)
.Include(e => e.Salary)
.AsNoTracking();
Generated SQL:
SELECT [e].[offence_id], [e].[amount], [e].[dt_recorded], [e].[guard_id], [e].[last_modified], [e].[last_modified_by], [e].[penalty_id], [e].[salary_id], [e].[site_id], [e].[status], [e.Salary].[salary_id], [e.Salary].[dt_paid], [e.Salary].[guard_id], [e.Salary].[last_modified], [e.Salary].[last_modified_by], [e.Salary].[period], [e.Site].[site_id], [e.Site].[address], [e.Site].[client_id], [e.Site].[last_modified], [e.Site].[last_modified_by], [e.Site].[name], [e.Site].[state], [e.Penalty].[penalty_id], [e.Penalty].[amount], [e.Penalty].[description], [e.Penalty].[dt], [e.Penalty].[last_modified], [e.Penalty].[last_modified_by], [e.Penalty].[name], [e.Guard].[guard_id], [e.Guard].[address], [e.Guard].[bank], [e.Guard].[dob], [e.Guard].[dt_joined], [e.Guard].[dt_trained], [e.Guard].[has_picture], [e.Guard].[height], [e.Guard].[last_modified], [e.Guard].[last_modified_by], [e.Guard].[location_id], [e.Guard].[marital_status], [e.Guard].[mobiles], [e.Guard].[name], [e.Guard].[nuban], [e.Guard].[ref_no], [e.Guard].[religion], [e.Guard].[salary], [e.Guard].[sex], [e.Guard].[state_origin], [e.Guard].[status]
FROM [Offences] AS [e]
left JOIN [Salaries] AS [e.Salary] ON [e].[salary_id] = [e.Salary].[salary_id]
left JOIN [Sites] AS [e.Site] ON [e].[site_id] = [e.Site].[site_id]
left JOIN [Penalties] AS [e.Penalty] ON [e].[penalty_id] = [e.Penalty].[penalty_id]
left JOIN [Guards] AS [e.Guard] ON [e].[guard_id] = [e.Guard].[guard_id]
ORDER BY [e.Guard].[name]
Found the solution, make all the foreign keys null-able, then EF.core uses a LEFT JOIN for the query instead:
public class Offence
{
[Key]
public Int32 offence_id { get; set; }
public Int32? guard_id { get; set; } // make null-able
public Int32? penalty_id { get; set; } // make null-able
public DateTime? dt_recorded { get; set; }
public Int32? salary_id { get; set; } // make null-able
public Decimal? amount { get; set; }
public String status { get; set; }
public Int32? site_id { get; set; } // make null-able
public Guard Guard { get; set; }
public Salary Salary { get; set; }
public Site Site { get; set; }
public Penalty Penalty { get; set; }
public DateTime? last_modified { get; set; }
public int? last_modified_by { get; set; }
}

Invalid Columns using EF

Can someone please help me with this problem? I am new to EF and i don't know what happen to this code:
Please find below query in the Controller:
foreach (var i in tt)
{
db.tbl_transaction.Add(i);
db.tbl_transactionlist.Add(tm.tlist);
var tools = (from j in db.tbl_tools_and_equips where j.itemno == i.controlno select j).First();
//tools.location = i.destinationid;
//tools.linemodel = i.line_model;
//tools.usage = i.process_assign;
tools.status = i.status;
tools.date_maintain = i.date_maintain;
tools.date_next_maintain = i.date_next_maintain;
}
try
{
/*return error: invalid columns in db.SaveChanges*/
db.SaveChanges();
For my Model:
public partial class tbl_transaction
{
public int transferevent { get; set; }
public string transactionno { get; set; }
public Nullable<int> itemno { get; set; }
public string assetdesc { get; set; }
public string serialno { get; set; }
public string barcode { get; set; }
public string sourcelocationid { get; set; }
public string destinationid { get; set; }
public Nullable<System.DateTime> transactiondate { get; set; }
public Nullable<int> quantity { get; set; }
public string unitmeasure { get; set; }
public string remarks { get; set; }
public string #ref { get; set; }
public string actg_rem { get; set; }
public string label { get; set; }
public string station { get; set; }
public string line_model { get; set; }
public string process_assign { get; set; }
public string status { get; set; }
public string controlno { get; set; }
public string category { get; set; }
public Nullable<System.DateTime> date_maintain { get; set; }
public Nullable<System.DateTime> date_repair { get; set; }
public string defect { get; set; }
public string repair_made { get; set; }
public Nullable<System.DateTime> date_next_maintain { get; set; }
}
Every time I execute the query, it always return invalid column name. Your help is very much appreciated.

Getting ObjectContext error even after calling ToList

When calling the method directly below I get a ObjectDisposedException when calling Mapper.Map with the retrieved list.
System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
public IEnumerable<Models.Provider> Get(string owner)
{
List<Data.Models.Provider> providers;
using (var db = new Data.ProviderDirectoryContext())
{
providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
}
var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
return dtoProviders;
}
I previously had the code like this (below), I wasn't getting an error, but the database was getting pounded when doing the mapping, and it was taking too long. I don't want to hit the database, when doing the mapping.
public IEnumerable<Models.Provider> Get(string owner)
{
using (var db = new Data.ProviderDirectoryContext())
{
var providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
return dtoProviders;
}
}
How can I retrieve all the data before doing the mapping?
Here is the DbContext and the Data.Models.Provider for your reference.
public class ProviderDirectoryContext : DbContext
{
public DbSet<Owner> Owners { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<LocationAuditLog> LocationAuditLog { get; set; }
public DbSet<Office> Offices { get; set; }
public DbSet<OfficePhoneNumber> OfficePhoneNumbers { get; set; }
public DbSet<OfficeAuditLog> OfficeAuditLog { get; set; }
public DbSet<OfficeDay> OfficeDays { get; set; }
public DbSet<Provider> Providers { get; set; }
public DbSet<ProviderPhoneNumber> ProviderPhoneNumbers { get; set; }
public DbSet<ProviderAuditLog> ProviderAuditLog { get; set; }
public DbSet<ProviderType> ProviderTypes { get; set; }
public DbSet<ProviderSpecialty> ProviderSpecialties { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Provider>().HasRequired(cn => cn.Owner).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<Office>().HasRequired(cn => cn.Owner).WithMany().WillCascadeOnDelete(false);
}
}
public class Provider
{
public int Id { get; set; }
public int OwnerId { get; set; }
public virtual Owner Owner { get; set; }
public int? ProviderTypeId { get; set; }
public virtual ProviderType ProviderType { get; set; }
public int? ProviderSpecialtyId { get; set; }
public virtual ProviderSpecialty ProviderSpecialty { get; set; }
[Required]
[StringLength(75)]
public string FirstName { get; set; }
[StringLength(75)]
public string MiddleName { get; set; }
[Required]
[StringLength(75)]
public string LastName { get; set; }
[StringLength(100)]
public string EmailAddress { get; set; }
public virtual ICollection<ProviderPhoneNumber> PhoneNumbers { get; set; }
public string Note { get; set; }
public DateTime? InactiveOn { get; set; }
public int OfficeId { get; set; }
public virtual Office Office { get; set; }
public virtual ICollection<ProviderAuditLog> AuditLog { get; set; }
[Required]
public DateTime CreatedOn { get; set; }
[Required]
[StringLength(75)]
public string CreatedBy { get; set; }
[Required]
public DateTime ModifiedOn { get; set; }
[Required]
[StringLength(75)]
public string ModifiedBy { get; set; }
}
Thanks for the help!
The problem is that the Models.Provider class contains other classes like Models.Office, and Models.PhoneNumbers that were not eagerly loaded by the query. In addition to that, the Models.Provider class needs to be flattened. The Mapper wants to recursively map everything, and it keeps going down to the next class. For example, Provider.Office.Location.Offices.
The solution is to flatten Models.Provider and add .Include() to the query so it eagerly loads the data required.
I'll clean this up a bit more, but this is currently working.
public IEnumerable<Models.Provider> Get(string owner)
{
List<Data.Models.Provider> providers;
using (var db = new Data.ProviderDirectoryContext())
{
providers = db.Providers
.Where(p => p.Owner.Name == owner)
.Include("ProviderType")
.Include("ProviderSpecialty")
.Include("Office")
.Include("PhoneNumbers")
.ToList();
}
var dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
return dtoProviders;
}
public class Provider
{
public int Id { get; set; }
public int OwnerId { get; set; }
public int OfficeId { get; set; }
public string OfficeName { get; set; }
public int? ProviderTypeId { get; set; }
public string ProviderTypeName { get; set; }
public int? ProviderSpecialtyId { get; set; }
public string ProviderSpecialtyName { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
public string Note { get; set; }
public DateTime? InactiveOn { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
}
I am not sure how much this will help with performance but declaring the variable you don't want to dispose outside the using statement should fix your dispose exception.
public IEnumerable<Models.Provider> Get(string owner)
{
IEnumerable<Models.Provider> dtoProviders;
using (var db = new Data.ProviderDirectoryContext())
{
List<Data.Models.Provider> providers = db.Providers.Where(p => p.Owner.Name == owner).ToList();
dtoProviders = Mapper.Map<List<Data.Models.Provider>, List<Models.Provider>>(providers);
}
return dtoProviders;
}