New Posts New Posts RSS Feed: Relationship Entities are Read-only
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Relationship Entities are Read-only

 Post Reply Post Reply
Author
sebma View Drop Down
Groupie
Groupie
Avatar

Joined: 19-Aug-2008
Location: Singapore
Posts: 66
Post Options Post Options   Quote sebma Quote  Post ReplyReply Direct Link To This Post Topic: Relationship Entities are Read-only
    Posted: 17-Sep-2008 at 9:05am
Hi all,
 
I have a typical object hierarchical group structure in which a Group and have Sub-groups and so on.
I managed to mapped this recursive relationship table(RelGroups) for this database table (TrainingGroup):
 
TrainingGroup
InternalId Name
======= ====
1               Root
2               GroupA
3               GroupB
 
RelGroups
ParentId ChildId
====== =====
1             2
1             3
 
On the edmx side, it also generated the relationship mapping and I named them as ParentGroups and ChildGroups of a TrainingGroup. (I attached the edmx as well)
 
From the above I can retrieve from EntityManager the Root instance having GroupA and GroupB as children instances.
 
However, the DevForce EF generated domain model does not allow me to add/update/delete the ParentGroups or ChildGroups because they are read-only. See Create method below.
 
    public static TrainingGroup Create(EntityManager manager, string name, TrainingGroup parent)
    {
        TrainingGroup newChildGroup = manager.CreateEntity<TrainingGroup>();
        // Add custom code here
        newChildGroup.AddToManager();
        newChildGroup.Name = name;
        newChildGroup.ParentGroups.Add(parent); // ERROR! ParentGroups is read-only
        parent.ChildGroups.Add(newChildGroup);  // ERROR! ChildGroups is read-only
        return newChildGroup;
    }
 
Is there anyway to create a new TrainingGroup instance and a new relationship (ParentGroup and ChildGroup) in one transaction as above? Right now I cannot because the relationship generated is read-only.
 
 
 
 
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 17-Sep-2008 at 1:59pm
Sebma:
 
The Add() method on navigation properties is the one feature of the Entity Framework not currently supported by DevForce EF. This does not constitute a problem for one-to-many navigation properties, as simply adding the child and setting its foreign key to the appropriate parent will cause it to show up in the parent's list of children. 
 
It is, however, a problem with many-to-many associations where the linking entity has no "payload"; i.e., it has no properties other than the two foreign keys.  This is the situation you have.  The reason it is a problem is that, as you know, the Entity Framework does not expose the linking entity when it has no payload. You can't add a RelGroup because no such entity exists!
 
We plan to implement support for Add() in a (soon) forthcoming release. For now your options are these:
 
Option 1. Expose the linking entity so you have something to add to. The best way to see how to do this is to go through the following process with a scratch model against a simple scratch database:
 
a. Create a linking entity with a payload column -- anything -- and generate an Entity Data Model from it.
b. Remove the payload column from the table and remove the corresponding property from the conceptual entity. 
 
The linking entity will remain exposed, with only its two foreign key columns. [1]
 
Option 2. Add a payload column *permanently* to the linking entity (and update the model).  This is the option we recommend, for a couple of reasons. First and foremost, it eliminates the somewhat painful reengineering that you'll have to undertake if you decide downstream that your linking entity really needs a payload (i.e., there's some piece of information you want to track about the association itself). We find that it is a very common occurrence for linking entities to evolve into entities that have importance in their own right and have to carry several pieces of information above and beyond the linking information itself.  Secondly, the payload can be an arbitary, single-column foreign key: something we also like. That's probably the kind of key you have for your other entities, and it's nice to have all of your entities operate the same way with respect to the primary key.
 
FYI, we'll still recommend Option 2 even after we support the Add() method. The Add() functionality won't eliminate the aggravating reengineering involved in adding a payload to a linking entity that started life without one.
 
Regards,
Greg Dunn
IdeaBlade
 
 
[1] As an aside, we recommend that you *always* make a backup of your EDMX before you do any twiddling of any sort, until you're *very* familiar with the operation you're about to perform. It's easy to get an EDMX hosed up in a way that's difficult to recover from unless you really know your way around. 
 
Back to Top
sebma View Drop Down
Groupie
Groupie
Avatar

Joined: 19-Aug-2008
Location: Singapore
Posts: 66
Post Options Post Options   Quote sebma Quote  Post ReplyReply Direct Link To This Post Posted: 18-Sep-2008 at 2:31am
I used Option 2 as recommended, i.e. Added a new payload column to my linking entity (RelGroups) in database table, backed-up and removed my old edmx, re-generated the new edmx and then the domain model. Now I have access to RelGroups entity and could add new sub-group entity with the following sample codes:

    /// <summary>
    /// Use this factory method template to create new instances of this class
    /// </summary>
    /// <param name="manager">The DevForce EntityManager</param>
    /// <param name="name">The name for the new group</param>
    /// <param name="parent">The parent TrainingGroup</param>
    /// <param name="childLevel">The child node level in the group tree (This is the new "payload column" for information only), will persist to RelGroups.ChildLevel.</param>
    /// <returns></returns>
    public static TrainingGroup Create(EntityManager manager, string name, TrainingGroup parent, int childLevel)
    {

        TrainingGroup newChildGroup = manager.CreateEntity<TrainingGroup>();

        // if this object type requires a unique id and you have implemented
        // the IIdGenerator interface implement the following line
        //manager.GenerateId(aTrainingGroup, // add id column here //);

        // Add custom code here

        newChildGroup.AddToManager();
        newChildGroup.Name = name;
        RelGroup rel = RelGroup.Create(manager, parent, newChildGroup, childLevel);

        return newChildGroup;
    }

Thank-you Greg and IdeaBlade's excellent dev support!

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down