Entity Framework Core not loading related data - entity-framework

We are developing a new application using ASP.NET Core and EF Core. We're on the latest stable release (v1.1.2). We are unable to load related data via navigation properties.
I am aware that lazy loading is not supported in EF Core but every post on the subject I have looked at suggests that we should be able to explicitly load related data using .Include(). However, this is not working for us and the related entities are always null when we load them in code.
We have two entities - 'Exchange' and 'Trade'. 'Exchange' has a foreign key to 'Trade' and contains a Virtual Trade called Request and another called Offer, thus:-
[Table("Exchange")]
public partial class Exchange : BaseEntity
{
public string Pending { get; set; }
[Display(Name = "Exchange Date"), DataType(DataType.Date)]
public DateTime DateOfExchange { get; set; }
public decimal EstimatedHours { get; set; }
public decimal ActualHours { get; set; }
public string Description { get; set; }
public string FollowUp { get; set; }
public string Status { get; set; }
[ForeignKey("User")]
[Required]
public int Broker_Fk { get; set; }
public virtual User Broker { get; set; }
public int Request_Fk { get; set; }
public virtual Trade Request { get; set; }
public int Offer_Fk { get; set; }
public virtual Trade Offer { get; set; }
I have a View Model that instantiates an 'Exchange' which I know has a related 'Request':-
_vm.Exchanges = _context.Exchange.Include(i => i.Request).Where(t => t.Request.User_Fk == user.Id || t.Offer.User_Fk == user.Id).ToList();
This returns an Exchange, which I am passing to and rendering in the View Model:-
#foreach (var item in Model.Exchanges)
{
<span>#item.Request.Name</span> <br />
}
The problem is that #item.Request is null, even though I have explicitly included it when loading the Exchange. I know that there really is a related entity in existence because one of the other properties on Exchange is its foreign key, which is populated.
What am I missing? Every example I have seen posted suggests that what I've done should work.

Your model attributes are messed up:
[Table("Exchange")]
public partial class Exchange : BaseEntity
{
//...
[ForeignKey("Broker")]
[Required]
public int Broker_Fk { get; set; }
public virtual User Broker { get; set; }
[ForeignKey("Request")]
public int Request_Fk { get; set; }
public virtual Trade Request { get; set; }
//...
}

Related

Can't get stored procedure in entity framework to return values

I tried creating a stored procedure in my DB and I tested it in Sql Server Management Studio (works fine), but when I call it from my MVC application using entity framework the results say - "Children could not be evaluated" when I expand on the results view.
Here is what I've tried so far.
public void ExecuteStoredProcedure()
{
//var gift = context.Gifts.SqlQuery("dbo.GetGiftsFromId #p0", 1);
var result = context.Database.SqlQuery<Gift>("dbo.GetGiftsFromId #p0", 1);
}
Inside my stored procedure I have one line to execute.
SELECT * from dbo.Gifts where GiftId = #gift_id
Does anyone have any ideas as to why the call isn't returning anything? I see in other posts that some people are using modelbinder.Entity etc, etc in their code. Do I need to do this?
I'm using code first and here is my gift object
public class Gift
{
// for a one-to-one relationship
// great tutorial on code-first
//http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
public Gift()
{
Images = new List<GiftImage>();
}
public int GiftId { get; set; }
public DateTime DateCreated { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<GiftCategory> Categories { get; set; }
public int Rating { get; set; }
public GiftStatus Status { get; set; }
[Required]
public int OwnerId { get; set; }
[Required]
public virtual GiftAddress GiftAddress { get; set; }
public GiftAvailability Availability { get; set; }
[Required]
public virtual GiftDescription Description { get; set; }
public byte[] Thumbnail { get; set; }
[Required]
public virtual ICollection<GiftImage> Images { get; set; }
public ICollection<GiftReview> Reviews { get; set; }
}
I have to use.
results.ToList()
to get the results.
or something that takes the results and does something with it.

Multi-Tenant and EF6 Design

I'm designing a multi tenant website using EF6 code first, MVC, and other from the MS stack.
I want to have announcements for each Tenant. Simple enough, my EF code first class would look something like this:
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public virtual Tenant Tenant { get; set; }
public ApplicationUser Author { get; set; }
}
My design question is what if I want the site administrator to have the ability to post announcements to all tenants?
Since the database will force the Tenant relationship, I can't set the Tenant property to something artificial.
Before EF, I'd do something like this, but now I will lose the nice-to-have EF Navigation property.
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public int TenantID { get; set; }
public ApplicationUser Author { get; set; }
}
I would use TenantID appropriately for all Tenant based announcements, but would set it to 0 for site wide announcements.
So, is there a better design (other than two classes/tables) that can still leverage the EF Navigation properties?
What is the issue with
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public virtual int Id { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual string Title { get; set; }
public virtual string Message { get; set; }
public virtual int TenantID { get; set; } // during insert/Update set as required. the tenant should exist.
// A dummy SYSTEM wide tenant may be an option to consider
// navigation props
[ForeignKey("TenantID")]
public virtual Tenant Tenant { get; set; } // <<<<< NAV as before
public virtual ApplicationUser Author { get; set; }
}

Advanced TPH Mapping to Legacy Database

I have been working on a project in which I am trying to mold entity framework to an existing FoxPro 2.x database in order to use the data while leaving the tables readable to a legacy application (more details on my previous question).
I've had pretty good luck configuring the DBContext to the physical data tables and I have most of my mapping set up. The legacy data structure has a Bills table with a unique primary Id key, but all the LineItems that can be posted to a bill are stored in a single Charges table without a simple primary key.
My question pertains to discriminator mapping in code-first EF. I am recreating the table as TPH in my data objects, so I have
public abstract class Posting
{
public System.DateTime? Post_Date { get; set; }
public string Bill_Num { get; set; }
public string Type { get; set; }
public string Pcode { get; set; }
public string Pdesc { get; set; }
public decimal? Custid { get; set; }
public string Createby { get; set; }
public System.DateTime? Createdt { get; set; }
public string Createtm { get; set; }
public string Modifyby { get; set; }
public System.DateTime? Modifydt { get; set; }
public string Modifytm { get; set; }
public string Linenote { get; set; }
public decimal? Version { get; set; }
public string Id { get; set; }
public string Batch { get; set; }
public virtual Billing Bill { get; set; }
}
public abstract class Charge : Posting
{
}
public class ServiceLine : Charge
{
public string Chargeid { get; set; }
public virtual ICollection<Payment> Payments { get; set; }
}
public class ChargeVoid : Charge
{
}
public abstract class Payment : Posting
{
}
public class PaymentLine : Payment
{
public string Postid { get; set; }
public string Svc_Code { get; set; }
public string Name { get; set; }
public string Checkno { get; set; }
public System.DateTime? Checkdate { get; set; }
}
public class PaymentVoid : Payment
{
}
where my mapping strategy so far is along these lines:
public class PostingMap : EntityTypeConfiguration<Posting>
{
public PostingMap()
{
// Primary Key
this.HasKey(t => new {t.Bill_Num, t.Post_Date, t.Pcode});
this.Map<Charge>(m => m.Requires("Type").HasValue("C"))
.ToTable("Charges");
this.Map<Payment>(m => m.Requires("Type").HasValue("P"))
.ToTable("Charges");
}
}
I have omitted some fields and mapping classes, but this is the core of it.
Every record has the C/P classification, so this makes everything in the table either a Charge or a Payment.
Every Posting is associated with a Bill via Bill_Num foreign key.
The ServiceLine object is only distinct from ChargeVoid objects (which are adjustment entries and no-value information entries associated with a bill) by having values for Pcode and Chargeid (which is just Bill_Num tagged with 01++). I have no idea how to model this.
It is very similar for the Payment hierarchy as well.
So with my current setup, I have Postings which doesn't have a unique key, Charges which has a subset of ServiceLines with values for Chargeid and Pcode and a subset with nulls, and Payments similar to Charges. PaymentLines are also many-to-one with ServiceLines by way of Pcode while PaymentVoids have Pcode = null.
Is there a way I can assign this complex mapping since I can't simply discriminate on !null? On top of that, will EF handle the key assignments once I get the inheritance set up, or am I going to have issues there as well?
Also, if there is a better way to break this object inheritance down, I am all ears.

EF Code-First creates some fields ,even I added ForeignKey annotations

can any one help me in this ?
Here is my 2 classes
class Request
{
public Nullable<int> BuyCurrencyId {get ; set;}
public Nullable<int> SaleCurrencyId {get ; set;}
[ForeignKey("SaleCurrencyId")]
public virtual Currency SaleCurrency { get; set; }
[ForeignKey("BuyCurrencyId")]
public virtual Currency BuyCurrency { get; set; }
}
class Currency
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Request> Requests { get; set; }
public virtual ICollection<Request> Requests1 { get; set; }
}
I checked the updated with EF database , and I found out that the EF create Reqyests table like this :
SaleCurrencyId int (Already exists)
BuyCurrencyId int (Already exists)
Currency_Id int (Added by EF)
Currency_Id1 int (Added by EF)
By this not thing I expect. I thing the last tow columns are not correct and they not be exist.
Can any one help me ?
I am using EF 6 alpha to update the existing database with my generated model by T4.Please keep it in mind that I want to use data annotations , not Fluent API
Sorry about my bad English
Update 1 :
I thought if I change the Currency class to this it will resolve my problem , but it did not.
class Currency
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("SaleCurrencyId")]
public virtual ICollection<Request> Requests { get; set; }
[InverseProperty("BuyCurrencyId")]
public virtual ICollection<Request> Requests1 { get; set; }
}
Your Update1 is almost the correct solution, but the parameter of the [InverseProperty] attribute must be the navigation property in Request, not the foreign key property:
[InverseProperty("SaleCurrency")]
public virtual ICollection<Request> Requests { get; set; }
[InverseProperty("BuyCurrency")]
public virtual ICollection<Request> Requests1 { get; set; }

breeze.js one to many

I'm currently building an SPA with Web API and knockout etc. So far i worte my own simple datacontext and it worked pretty well.
The I bumped in to breeze and thought it might be worth a try. especially I hoped to get a simpler approach on navigation between the entities...
to load a entities or a single entity with breeze worked fine. Working with navigation properties seems not to work. The navigation property is always empty, even though it's a one to many relationship.
Here is my model (simplified):
public class WorkdayHours
{
public int Id { get; set; }
public bool IsWorkDay { get; set; }
...
public Byte WeekDay { get; set; }
}
public class Service
{
public int Id { get; set; }
public string DisplayName { get; set; }
public virtual ICollection<WorkdayHours> BookableDays { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string DisplayName { get; set; }
public virtual ICollection<WorkdayHours> BookableDays { get; set; }
}
public class Shop
{
public int Id { get; set; }
public string DisplayName { get; set; }
public virtual ICollection<WorkdayHours> BookableDays { get; set; }
}
Then I fetch the entity service ind my SPA as follow:
var query = EntityQuery
.from('Services')
.where('id', 'eq', serviceId)
.expand('BookableDays');
As when teh query is executed I get as result the requested service entity with all the data except the bookableDay property is always an empty array.
When I check the Json answer I see that also the workdayHours are transmitted and breeze even calls my defined ctors for this entities. However they are not linked to the bookableDays property itself.
When checking the genrated DB model, EF generated foreignkeys for service, employee and shop in workdayHours as expected.
Is breeze not capable with having several optional foreignkeys?
Suggestion and ideas highly apprechiated.
Breeze is dependent on Foreign Keys. I had a similar problem. This should solve it:
EF was generating the ForeignKeys for me too and the related Entites where still empty. As far as i know breeze needs the explicit Annotation/Configuration of ForeignKey Fields.
public class Mvl
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long MvlId{ get; set; }
public DateTime CreatedAt { get; set; }
[InverseProperty("Mvl")]
public ICollection<MvlOP> MvlOps { get; set; }
public DateTime? ReleasedAt { get; set; }
public DateTime? LockedAt { get; set; }
public DateTime? ClosedAt { get; set; }
//[ConcurrencyCheck]
//public int? RowVersion { get; set; }
[Timestamp]
public byte[] TimeStamp { get; set; }
}
public class MvlOP
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long MvlOpId { get; set; }
public long MvlId { get; set; }
[ForeignKey("MvlId")]
public Mvl Mvl { get; set; }
...
}