EF code first related entities not loading at all - entity-framework

I haven't been able to find someone else with this issue specifically so here goes.
I have a simple model where one entity simply references another as a parent-child or one-to-many relationship defined like this:
public class Parent
{
public int ID { get; private set; }
public string Name { get; private set; }
}
public class Child
{
public int ID { get; private set; }
public string Name { get; private set; }
public virtual Parent Parent { get; private set; }
}
I am creating speicific mapping files for each, which work great for all the normal properties except for the related entity. It is always coming up null. No matter whether i have the virtual/private accessors on the property it will not load UNLESS i pull a copy of the parent separately from the context first. My mapping looks like this:
HasRequired(t => t.Parent).WithMany().Map(t => t.MapKey("ParentID")).WillCascadeOnDelete();
Is there anything I am doing wrong with this? I cannot for the life of me figure this out. Just so I cover all the bases, I am loading the entity like this:
Context.Set<Child>().FirstOrDefault(x => x.ID == 1);
And lastly here are some constraints I have:
I cannot have the foreign keys in my model as properties.
I cannot have a collection of children from the parent.

I finally figured it out. After much trial and error I noticed that having a parameterless constructor marked as internal, EF cannot create its dynamic proxy class of your type and therefore disables all lazy loading. I have two contructors, one for EF to hydrate objects, and another with parameters requires for callers to create my entity. Once I changed the signature to protected internal it started working. So I changed this:
internal Child() {}
to
protected internal Child() {}

May be you hasn't enable lazy loading .Try this,
Context.Set<Child>().FirstOrDefault(x => x.ID == 1).Include(c=>c.Parent);

Related

Deleting association between one or zero to one entities with EntityFramework

I have entities set up something like this:
public class MyThing
{
public int Id { get; set; }
public virtual MyOtherThing { get;set; }
}
public class MyOtherThing
{
public int Id { get; set; }
public virtual MyThing MyThing { get; set; }
}
My intention is that 'MyThing' can have one or none of MyOtherThing, and I also want a navigation link from MyOtherThing to it's parent.
I have configured the following EntityBaseConfiguration for the 'MyOtherThing' entity:
this.HasOptional(x => x.MyThing)
.WithOptionalPrincipal(x => x.MyOtherThing);
I can assign and modify MyOtherThing to MyThing no problem, but when I want to unassign 'MyOtherThing' from 'MyThing', how do I do this?
I tried the following:
myThing.MyOtherThing = null;
and then editing the entity by setting the EntityState.Modified state, but this didn't remove the association between the entities.
I tried adding the following to my MyThing entity, but this resulted in an EF 'Multiplicity is not valid' error when updating my database model:
public int? MyOtherThingId{ get; set; }
Thanks in advance!
I tried the following:
myThing.MyOtherThing = null;
If you want to remove an optional dependent entity (here: MyOtherThing) from a principal entity (here MyThing) by setting it to null, you have to pull the entity from the database with the dependent entity included, for example:
var mything = context.MyThings.Include(m => m.MyOtherThing)
.Single(t => t.Id == idValue);
(It's also OK when the belonging MyOtherThing is loaded into the context later, for example by lazy loading).
Without Include, myThing.MyOtherThing already is null and EF doesn't detect any change. Note that the statement myThing.MyOtherThing = null; doesn't execute lazy loading, which is a bit confusing because with collections the behavior is different.
By the way, the dependent entity can also be removed from the database directly, which is more efficient.
var ot = context.Set<MyOtherThing>().Find(idValue);
context.Set<MyOtherThing>().Remove(ot);
context.SaveChanges();

Mapping custom collection's property to column in EF

I'd like this class:
public class InvertedList<T> : List<T>{
public bool IsInverted { get; set; }
}
when used in the entity like this:
public class Parent {
public InvertedList<Child> Children { get; set; }
}
to map into database tables like
CREATE TABLE Parent (
Child_IsInverted bit
);
CREATE TABLE Child (
ParentId int
)
I've tried putting [Column] on the IsInverted property, [ComplexType] on InvertedList class, but the property is always ignored.
Is there any way to do something like this or anything similar?
Of course I can do it manually like
public class Parent {
public bool Child_IsInverted { get; set; }
public List<Child> Children { get; set; }
}
But I really don't like to put all those Child_IsInverted properties (I'll have quite a lot of such invertable lists) on Parent entity. The only way I can think of to at least partially implement this would be to have separate domain and db models, and transform it using the repository - this way I could work using desirable model, but it looks like a little bit too much effort for such a task. Can you offer any other options?
When EF deserialize a List<> (everything implementing ICollection<>) it does not serialize other properties than the content.
Just a suggestion, Compex types that could be an option does not support generics and does not support navigation properties and you here have both.

Issue with Entity Framework TPT hierarchy and relationships

my current EF6 implementation goes somewhat like this:
public class Parent
{
public int Id { get; set; }
public virtual string Name { get; set; }
public string Description { get; set; }
public virtual ICollection Children { get; set; }
public int OtherEntityId { get; set; }
public virtual OtherEntity OtherEntity { get; set; }
}
public class Child : Parent
{
public int Id { get; set; }
public override string Name
{
get { return Parent == null ? "Dummy" : Parent.Name; }
}
public string Description { get; set; }
public ParentId { get; set; }
public virtual Parent { get; set; }
public override int OtherEntityId
{
get { return Parent == null ? default(int) : Parent.OtherEntityId; }
}
}
The fluent configuration for the Child goes like this:
this.ToTable("Child")
.HasRequired(x => x.Parent)
.WithMany(x => x.Children)
.HasForeignKey(xy => xy.ParentId);
The idea is to have one entry for every Parent and Child in my Parent table.
Yet, the Child entity should not have a name of its own, but get the name from it's parent.
I also need a way to navigate from every child to its parent.
And I also need a way to navigate from every parent to its children.
This only goes over 1 level.
The reason for this implementation was due to the requirement to always get certain values from the parent, yet the Child must have the same public interface as the Parent.
Keep in mind that I can't change the Parent here, it is part of a framework I have to stick with. So only the child is actually part of my implementation.
The problem seems to be with the change tracking.
If I query for a Child, EF loads the Child first, checks all properties, and loads the Parent second. Since now the name is different, for EF the name property already changed, even though I have not changed it manually.
The solution works somewhat, as long as I load the all entities without tracking. The moment I try to load them with tracking enabled I get an exception:
A referential integrity constraint violation occurred:
A primary key property that is a part of referential integrity
constraint cannot be changed when the dependent object is Unchanged
unless it is being set to the association's principal object.
The principal object must be tracked and not marked for deletion.
Same happens if a try to attach the entity after loading, and set its state to Unchanged.
I do not change primary keys, or any keys at all, so it is not clear to me, why this error happens.
It seems that the error happens during the relationship fixup.
I fear its the "OtherEntityId" but I can't verify it, since I have no idea how to debug it.
Anyone has ideas what the problem might be or how I can debug that properly?
I tried to get the internal values with something like:
https://www.exceptionnotfound.net/entity-change-tracking-using-dbcontext-in-entity-framework-6/
But
ChangeTracker.Entries().Where(p => p.State ==
EntityState.Modified).ToList();
also seams to force a relationship fixup which leads to the error.

Entity Framework table splitting - how to initialize lazy-loaded properties?

Using Entity Framework 6.0, I am attempting to implement table splitting to improve query performance on tables with columns that contain BLOB data. I have followed the recommendations in this tutorial and it does indeed work as described.
Here's a very simplified example of the entity classes that map to one of my split tables ...
public class MyEntity
{
public string Id { get; set; }
public virtual MyEntityContent Content { get; set; }
public string Name { get; set; }
}
public class MyEntityContent
{
public string Id { get; set; }
public virtual MyEntity Entity { get; set; }
public byte[] Blob { get; set; }
}
... and the corresponding configuration code in the associated DbContext implementation ...
modelBuilder.Entity<MyEntity>().HasKey(e => e.Id).ToTable("MyEntities");
modelBuilder.Entity<MyEntityContent>().HasKey(c => c.Id).ToTable("MyEntities");
modelBuilder.Entity<MyEntity>().HasRequired(e => e.Content).WithRequiredPrincipal(d => d.Entity);
Given that the lazy-loaded Content property is Required by Entity Framework, it seems sensible to initialize it to a default value in the constructor of the containing MyEntity class ...
public MyEntity()
{
Content = new MyEntityContent();
}
... which enables a new instance of the class to be created and partially populated, without the risk of an exception being thrown by forgetting to initialize the required property value:
var entity = new MyEntity {Id = "XXX", Name = "something"};
I typically use a similar technique to initialize collection properties on EF entities and it works fine. However, in the above scenario, this initialization in the constructor has an unexpected effect: when retrieving existing entity instances from the database, the database value in the lazy-loaded property is ignored in favor of the empty default value.
This seems illogical to me. Doesn't Entity Framework create an entity object by first calling its default constructor and then applying its own property values to the created instance? If so, this should overwrite my default Content property value with a new instance of MyEntityContent, based on database data. This is how it seems to work with lazy-loaded collection properties.
If it's not possible to do this in the way I am expecting, is there an alternative technique for initializing lazy-loaded properties?
Don't initialize virtual members and perhaps, if you have to, handle any exceptions from uninitialized members.
I just had this issue with an entity with two virtual fields. Originally I had it initialize those two, but after removing them (and initializing the other fields to some default value), it started working for me. Try it out and let me know!
[Edit] I just realized I replied this to a slightly old post, didn't see the date. I guess I'll leave this answer here in case.

InverseProperty with Database Migration doesn't work when property is protected or internal

I have the following Entity Models
public class User
{
public virtual long Id{get; set;}
[InverseProperty("Users")]
public virtual ICollection<Tag> Tags { get; protected set; }
}
public class Tag
{
public virtual long Id{get; set;}
internal protected virtual ICollection<User> Users { get; set; }
}
This is pure simple many-to-many relation User & Tag
I'm using Data Migrations. When I execute the command Add-Migration or Update-Database
I get the following error "The InversePropertyAttribute on property 'Tags' on type 'Kigg.DomainObjects.Entities.User' is not valid. The property 'Users' is not a valid navigation property on the related type 'Kigg.DomainObjects.Entities.Tag'. Ensure that the property exists and is a valid reference or collection navigation property."
When I changed the access modifier of Users property in Tag to public it worked fine and the generation is what I want.
From my design point of view I want to hide the Tag.Users property and make it protected or internal to keep it for internal use as I don't want to expose it to public API.
Note: I'm not discussing the my design here. I'm asking if it's possible to do that while Tag.Users is protected or internal?
I don't know how to make it work with data annotations but with Fluent API you can apply and experiment with the trick from here: http://blog.cincura.net/232731-mapping-private-protected-properties-in-entity-framework-4-x-code-first/
For your model it would look like the following:
public class User
{
public virtual long Id{get; set;}
public virtual ICollection<Tag> Tags { get; protected set; }
}
public class Tag
{
public virtual long Id{get; set;}
internal protected virtual ICollection<User> Users { get; set; }
public class PropertyAccessors
{
public static readonly Expression<Func<Tag, ICollection<User>>> Users
= t => t.Users;
}
}
Mapping in FluentAPI:
modelBuilder.Entity<User>()
.HasMany(u => u.Tags)
.WithMany(Tag.PropertyAccessors.Users);
This works and creates the expected many-to-many relationship.
But I am not sure if you can do anything useful with that navigation property. The fact that you have the property protected and virtual lets me guess that you basically want lazy loading support inside of the entity class or derived classes.
The problem is that apparently (according to my tests at least) lazy loading doesn't work for anything else than a public property. The loaded tag is a proxy but the navigation collection is always null (unless the property is public).
Moreover, even eager and explicit loading don't work:
Outside of the Tag class:
// Eager loading
var tag = context.Tags.Include(Tag.PropertyAccessors.Users).First();
// Explicit loading
var tag2 = context.Tags.First();
context.Entry(tag2).Collection(Tag.PropertyAccessors.Users).Load();
Or inside of the Tag class (some method in Tag which gets the context passed):
public DoSomething(MyContext context)
{
// Eager loading
var tag = context.Tags.Include(t => t.Users).First();
// Explicit loading
context.Entry(this).Collection(t => t.Users).Load();
}
In all cases I get an exception that the property Users on entity Tag is not a valid navigation property. (The exception disappears as soon as I make the property public.)
I don't know if adding/removing/updating relationships would work. (I doubt.)
It looks that you can map a non-public navigation property with this approach to generate the expected database schema. But it seems that there is nothing useful you can do with it.
I don't know much about EF5 but you can use the attribute InternalsVisibleToAttribute to make internal members visible to a specific assembly.