Entity Framework Update nested list - c#

I use Entity Framework 6 (Code First). I have a class:
public class DialogSession {...}
And another class with a list of DialogSession objects:
public class DialogUser
{
public int Id { get; set; }
public List<DialogSession> DialogSessions { get; set; }
}
I add DialogSession object to the list and then execute context.SaveChanges() as follows:
dialogUser.DialogSessions.Add(dialogSession);
context.SaveChanges();
But the foreign key of the dialogSession record still Null:
I've tried using many methods on the web like the follows but withoyt success:
context.DialogUsers.Attach(dialogUser);
context.Entry(dialogUser).State = EntityState.Modified;
context.SaveChangesExtention();
Does anyone know how to save inner objects (like the list) in the database using Entity Framework (6)?

From your question is not clear which relationship type do you have, so I guess you have One-to-Many and something like this should works:
public class DialogSession
{
public int DialogSessionId { get; set; }
public virtual DialogUser DialogUser { get; set; }
}
public class DialogUser
{
public int DialogUserId { get; set; }
public virtual ICollection<DialogSession> DialogSessions { get; set; }
}
Take a look at example how properly configure this type of relationship in this article.

If I am not wrong you should add
dialogUser.DialogSessions.Add(dialogSession);
context.Entry(dialogUser).State = EntityState.Modified;
context.SaveChanges();
This will mark the entity as modified and then the changes should be reflected on the db.
This could be done a more efficiently by marking singular properties as modified
dialogUser.DialogSessions.Add(dialogSession);
context.Entry(dialogUser).Property(u => u.dialogSession).IsModified = true;
context.SaveChanges();
Give it a try :)

Please see: https://msdn.microsoft.com/en-us/library/jj591583(v=vs.113).aspx
You should use a virtual list for the child entity, and ensure that the DialogSessions class also refers back to its parent with a DialogUserId property (so named by convention)

The below works for me.
using System.ComponentModel.DataAnnotations;
public class DialogSession
{
[Key]
public int DialogSessionId { get; set; }
public int DialogUser { get; set; }
}
public class DialogUser
{
[Key]
public int DialogUserId { get; set; }
public virtual ICollection<DialogSession> DialogSessions { get; set; }
}

Related

Entity Framework model issue

I am having some strange issues, I am attempting to pull a record out of the database and it seems like most of it is null even know if I manually look in the DB it's populated.
Model
public class AdminConfiguration : Entity // Entity is an abstract class containing an ID
{
public bool Authentication { get; set; }
public List<ApplicationConfiguration> ApplicationConfiguration { get; set; }
public List<LinksConfiguration> LinksConfiguration { get; set; }
public EmailConfiguration EmailConfiguration { get; set; }
public bool WakeOnLan { get; set; }
}
Basically any reference to another class is null The only thing that is populated is the WakeOnLan property.
Query
public AdminConfiguration Find(int id)
{
return Db.AdminConfiguration.Find(id);
}
I have a feeling I have a misunderstanding regarding how I set up the models. I am expecting the query to return me a fully populated AdminConfiguration object.
Try to set navigation properties as virtual to enable lazy loading:
public virtual List<ApplicationConfiguration> ApplicationConfiguration { get; set; }
Please refer to https://msdn.microsoft.com/en-us/data/jj193542.aspx
This enables the Lazy Loading feature of Entity Framework. Lazy
Loading means that the contents of these properties will be
automatically loaded from the database when you try to access them.
The best way to setup your model is:
public class AdminConfiguration : Entity // Entity is an abstract class containing an ID
{
public AdminConfiguration()
{
this.ApplicationConfigurations = new HashSet<ApplicationConfiguration>();
this.LinksConfigurations = new HashSet<LinksConfiguration>();
}
public bool Authentication { get; set; }
public EmailConfiguration EmailConfiguration { get; set; }
public bool WakeOnLan { get; set; }
// Navigation properties
public virtual ICollection<ApplicationConfiguration> ApplicationConfigurations { get; set; }
public virtual ICollection<LinksConfiguration> LinksConfigurations { get; set; }
}

EntityFramework Schema specified is not valid. Errors:

Order Model
public partial class Orden
{
public Orden()
{
this.Orden_Bitacora = new HashSet<Orden_Bitacora>();
}
//Attributes list
public virtual ICollection<Orden_Bitacora> Orden_Bitacora { get; set; }
}
Orden_Bitacora Model
public partial class Orden_Bitacora
{
public int IdBitacora { get; set; }
public int IdOrden { get; set; }
public virtual Orden Orden { get; set; }
}
But when I try to create a Order always display me the message:
Schema specified is not valid. Errors:
The relationship 'OrdenexTModel.FK_Orden_Bitacora_Orden' was not
loaded because the type 'OrdenexTModel.Orden' is not available.
Its something wrong with the model declaration?
The relationship 'OrdenexTModel.FK_Orden_Bitacora_Orden' was not loaded because the type 'OrdenexTModel.Orden' is not available.
It cant find a Primary Key on Ordan and therefore the FK relationship will not work.
Add the PK to Orden
public partial class Orden
{
public int OrdenId { get; set; }
public Orden()
{
this.Orden_Bitacora = new HashSet<Orden_Bitacora>();
}
//Attributes list
public virtual ICollection<Orden_Bitacora> Orden_Bitacora { get; set; }
}
and you may need to add [Key] attribute to your Orden_Bitacora PK as it doesnt follow the Entity Framework naming convention
[Key]
public int IdBitacora { get; set; }
or
public int Orden_BitacoraId
Hope that helps
Go to EntityFramework .edmx file which will open an entity framework, Right click and select Update Model from Database, select okey it will get updated as changes might have done in database.

How to make proper code-first relations

I'm fairly new to Entity Framework and feel more in control using the Code-First pattern rather than DB-First.
I was wondering what is more preferred when it comes to programmatically setting up ForeignKey relations between the entities.
Is it better to declare a FK_ property in the class which relates to the another class or is it better to declare an IEnumerable<> property in the class that gets related to?
public class IRelateToAnotherClass
{
...
public int FK_IGetRelatedToByAnotherClass_ID { get; set; }
}
or
public class IGetRelatedToByAnotherClass
{
...
public IEnumerable<IRelateToAnotherClass> RelatedTo { get; set; }
}
It all depends on what type of relationships you want between your entities (one-to-one, one-to-many, many-to-many); but, yes, you should declare foreign key properties. Check out this site for some examples.
Here's a one-to-many for your two classes:
public class IRelateToAnotherClass
{
public int Id { get; set; } // primary key
public virtual ICollection<IGetRelatedToByAnotherClass> IGetRelatedToByAnotherClasses { get; set; }
}
public class IGetRelatedToByAnotherClass
{
public int Id { get; set; } // primary key
public int IRelateToAnotherClassId { get; set; } // foreign key
public virtual IRelateToAnotherClass IRelateToAnotherClass { get; set; }
}
and with some Fluent API mapping:
modelBuilder.Entity<IGetRelatedToByAnotherClass>.HasRequired<IRelateToAnotherClass>(p => p.IRelateToAnotherClass).WithMany(p => p.IGetRelatedToByAnotherClasses).HasForeignKey(p => p.Id);
If I understand what you're asking correctly, you'd want both. You want an int FK property and an object property to use as the navigation property.
The end result would look something like this:
public class Employee
{
[Key]
public int EmployeeID { get; set; }
[ForeignKey("Store")]
public int StoreNumber { get; set; }
// Navigation Properties
public virtual Store Store { get; set; }
}
public class Store
{
[Key]
public int StoreNumber { get; set; }
// Navigation Properties
public virtual List<Employee> Employees { get; set; }
}
If you haven't already, take a look at navigation properties and lazy-loading. Note that EF is clever enough to figure out that an int StoreID property corresponds to an object Store property, but if they are named differently (such as without the ID suffix), you must use the [ForeignKey] annotation.

EF5 Model-First, DBContext code generation and derived class

I'm creating a EF5 entity model with the designer (VS2012), and used the EF5 DbContext generator as code generation item.
My model contains an entity deriving from another (not abstract).
So let's say the base entity is called BaseEntity, and the derived entity is DerivedEntity.
Now I see in the generated context class, that there is no
Public DbSet<DerivedEntity> DerivedEntities { get; set; }
defined.
Only
Public DbSet<BaseEntity> BaseEntities { get; set; }
is defined.
Is this normal ? And if yes, how do I query the derived entities in linq ?
I'm used to query like this:
using(var ctx = new EntityContainer)
{
var q = from e in ctx.DerivedEntities <-- but this is now not possible since it doesn't exist
select e;
return q.ToList();
}
Thanks for replying.
EDIT:
As requested, generated classes posted:
public partial class Scheduling
{
public int Id { get; set; }
public string Subject { get; set; }
public System.DateTime BeginDate { get; set; }
public System.DateTime EndDate { get; set; }
}
public partial class TeamScheduling : Scheduling
{
public int TeamId { get; set; }
public Nullable<int> AssignmentId { get; set; }
public virtual Team Team { get; set; }
public virtual Assignment Assignment { get; set; }
}
public partial class EntityContainer : DbContext
{
public EntityContainer()
: base("name=EntityContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Team> Teams { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<Country> Countries { get; set; }
public DbSet<Assignment> Assignments { get; set; }
public DbSet<ProductType> ProductTypes { get; set; }
public DbSet<AssignmentPreference> AssignmentPreferences { get; set; }
public DbSet<Scheduling> Schedulings { get; set; }
}
As you see, the EntityContainer class does not contain
public DbSet<TeamScheduling> TeamSchedulings { get; set; }
This is expected when you use inheritance the way you have. context.Schedulings contains both Scheduling objects and TeamScheduling objects. You can get the TeamScheduling objects only by asking for context.Schedulings.OfType<TeamScheduling>(). Note that you cannot meaningfully use context.Schedulings.OfType<Scheduling>() to get the others: that will also include the TeamScheduling objects.
You could alternatively try context.Set<TeamScheduling>(), but I'm not entirely sure that will work.
If your intention is to have two tables come up, say a parent Scheduling entity as well as a child TeamScheduling entity that has a foreign key back to the Scheduling entity, consider using a Table-per-Type (TPT) mapping as discussed here.
In essence, you should modify your "OnModelCreating" method to have the following code:
modelBuilder.Entity<TeamScheduling>().ToTable("TeamScheduling");
This explicitly tells EF that you want to have the TeamScheduling subclass to be represented as its own table. Querying it via LINQ would be simple as you would be able to do something like the following:
var teamScheds = context.Set<TeamScheduling>().Where(s => s.Id == 1).FirstOrDefault();

Entity Framework Many to many through containing object

I was curious if it is possible to map an intermediate table through a containing object.
public class Subscriber : IEntity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
private ChannelList _subscribedList { get; set; }
public int NumSubscribedChannels { get { return _subscribedList.Count(); } }
}
public class HelpChannel : IEntity
{
[Key]
public int Id { get; set; }
public string name { get; set; }
public string category { get; set; }
public int group { get; set; }
}
I need to have a subscriber table, channel table and an intermediate table to link a subscriber to his/her channels.
Is it possible to map the list that is within the ChannelList object to the Subscriber Model?
I figured that's probably not possible and that I would need to just have a private List for EF to map. But I wasn't sure if EF will do that for private variables. Will it?
I'm hoping that is does because if it has to be public to maintain the encapsulation.
You can map private properties in EF code-first. Here is a nice description how to do it. In your case it is about the mapping of Subscriber._subscribedList. What you can't do is this (in the context's override of OnModelCreating):
modelBuilder.Entity<Subscriber>().HasMany(x => x._subscribedList);
It won't compile, because _subscribedList is private.
What you can do is create a nested mapping class in Subscriber:
public class Subscriber : IEntity
{
...
private ICollection<HelpChannel> _subscribedList { get; set; } // ICollection!
public class SubscriberMapper : EntityTypeConfiguration<Subscriber>
{
public SubscriberMapper()
{
HasMany(s => s._subscribedList);
}
}
}
and in OnModelCreating:
modelBuilder.Configurations.Add(new Subscriber.SubscriberMapping());
You may want to make _subscribedList protected virtual, to allow lazy loading. But it is even possible to do eager loading with Include:
context.Subscribers.Include("_subscribedList");

Categories