Search code examples
wcfentity-frameworkwcf-data-servicesodata

Can't correctly add associated objects into Entity Framework Context


I have and entity framework project exposed via a data service:

public class VersionContext : DbContext
{
    public DbSet<VersionTreeEntry> VersionTreeEntries { get; set; }

    public DbSet<PluginState> PluginStates { get; set; }

    public static void SetForUpdates()
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<VersionContext, Configuration>());
    }
}

public class VersionTreeEntry
{
    public VersionTreeEntry()
    {
        Children = new List<VersionTreeEntry>();
        PluginStates = new List<PluginState>();
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    public virtual ICollection<VersionTreeEntry> Children { get; set; }

    public virtual ICollection<PluginState> PluginStates { get; set; }

    public virtual VersionTreeEntry Ancestor { get; set; }

    /// <summary>
    /// Links to the ProtoBufDataItem Id for the session state.
    /// </summary>
    public int DataId { get; set; }

    public string Notes { get; set; }

    [Required]
    public DateTime TimeStamp { get; set; }

    [MinLength(1, ErrorMessage = "Tag cannot have a zero length")]
    [MaxLength(20, ErrorMessage = "A tag name cannot contain over 20 characters")]
    public string Tag { get; set; }

    public bool IsUiNodeExpanded { get; set; }

    [Required]
    public string Version { get; set; }

    [Required]
    public string SessionName { get; set; }
}

public class PluginState
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    public string PluginName { get; set; }

    [Required]
    public byte[] Data { get; set; }
}

As far as I can see, the data classes are defined correctly. I try to create some new objects and add them into the context, with their relations intact:

var session = new Session();
session.SessionName = "My new session";

VersionTreeEntry versionTreeEntry = new VersionTreeEntry();
versionTreeEntry.SessionName = session.SessionName;
versionTreeEntry.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
versionTreeEntry.TimeStamp = DateTime.Now;

_versionContext.AddToVersionTreeEntries(versionTreeEntry);

foreach (var plugin in session.Plugins)
{
     using (var ms = new MemoryStream())
     {
           plugin.SaveState(ms);
           PluginState state = new PluginState();
           state.PluginName = plugin.PluginName;
           state.Data = ms.ToArray();

           versionTreeEntry.PluginStates.Add(state);
     }
}

_versionContext.SaveChanges();

The problem is that the PluginState instances never actually get added to the database. If I add code to add them manually to the context, they do get added, but the foreign key pointing back to the VersionTreeEntry is null.

Again, this is a WCF DataService rather than vanilla EF, any idea what might be wrong?

Cheers


Solution

  • Posting the answer here from the comment section.

    Agreed. The best way to do this is to call the following API:

    _versionContext.AddRelatedObject(versionTreeEntry, "PluginStates", state); 
    

    Thanks Pratik