1

I have the following database table:

ID  ParentID  LinksTo
---------------------
0   null      "1,2"
1   0         "0,2"
2   0         "1"

It's a hierarchical design, where each records points to a parent record from the same table. I know the LinksTo field is a very bad design, but the table is given, I cannot change that. (Note that the LinksTo field creates a sort of many-to-many relationship.)

Using Code-First EF, I have the following model class:

public class Item
{
  public int ID { get; set; }
  public int ParentID { get; set; }
  public string LinksTo { get; set; }

  public virtual Item Parent { get; set; }

  [InverseProperty("Parent")]
  public virtual ICollection<Item> Children { get; set; }
}

Now, how can I add a dynamic property to the model so that I can access the Item collections Item.LinksTo and Item.LinksFrom (the reverse) in code?

3
  • 1
    How come "the table is given" when it's Code-First? It would be a hell of a lot easier to normalize the data and then create a view to be consumed by whatever wretched code wants to see it in that "LinksTo" format. Commented Jan 30, 2015 at 5:22
  • It is my understanding that Code-First is the preferred approach with existing databases. I'm more comfortable with code than with a graphic designer anyway. (See also msdn.microsoft.com/en-us/data/jj590134). Could you tell me more about normalization of data? I have no clue what that means. Commented Jan 30, 2015 at 8:41
  • I wasn't aware that Code First could be used with existing databases to be honest. That video is underselling Database First a bit, maybe. The model diagram and classes can be automatically created and updated for you from the database. There's not generally any need to mess around with it unless your database doesn't specify foreign keys etc properly. You would know what normalization is intuitively even if you don't know the jargon. In this case field atomicity is violated, that's 1NF. Read the wiki articles on 1NF, 2NF, 3NF. Changing the DB is a non starter if it's in use by an app though. Commented Jan 31, 2015 at 0:16

1 Answer 1

1

I guess I'd do something like this:

private List<Item> _linkedItems;

private void UpdateLinksTo() {
    this.LinksTo = string.Join<string>(_linkedItems.Select(i => i.ID.ToString()));
}

[NotMapped]
public ReadOnlyCollection<Item> LinkedItems {
    get {
        if(_linkedItems == null) {
            _linkedItems = db.Items.Where(i => this.LinksTo.Split(',').Select(x => int.Parse(x)).Contains(i.ID)).ToList();
        }
        return _linkedItems.AsReadOnly();
    }
}

[NotMapped]
public void AddLinkedItem(Item item) {
    if(!_linkedItems.Select(i => i.ID).Contains(item.ID)) {
        _linkedItems.Add(item);
        UpdateLinksTo();
    }
}

That will give you access to a read-only collection with methods to alter it (you can also make a DeleteLinkedItem method) which is about as good as you're going to do I think.

I haven't checked to even see if this compiles, btw.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that looks like it will help me a lot! I am going to try it out on Monday. I don't see any code that would give me the Item.LinksFrom collection, would it be difficult to add that also?
It took me some time to figure it all out, but now I have it working thanks to your code! The "this" keyword is an important part, and I hadn't realized I can instantiate the data context ("db") inside the model. I haven't done the LinksFrom collection yet, but I see it involves doing a query on the database with substring matching to find the current id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.