0

I have several identical object groups, each of them consists of entities mapped to main table and couple linking tables, for example

//group1
class OrderNote
{
    public int OrderNoteId {get; set;}
    public virtual ICollecton<OrderNoteTag> OrderNoteTags {get; set;}
}
class OrderNoteTag
{
    public int OrderNoteId {get; set;}
    public int TagId {get; set;}
}
//////
//group 2
class ClientNote
{
    public int ClientNoteId {get; set;}
    public virtual ICollecton<ClientNoteTag> ClientNoteTags {get; set;}
}
class ClientNoteTag
{
    public int ClientNoteId {get; set;}
    public int TagId {get; set;}
}
/////

Now, I need a method which allows me to process the main objects by the same routine, so I won't have to duplicate the same code a lot of times. My idea is to have some base classes for notes and tags, the concrete types will inherit from them, and the method will accept the base type for note. But I can't figure out how to declare and inherit the navigation properties , so they are mapped on the concrete tag type, but can be processed as base type.

Here's something like it should be:

public class TagBase
{
    public int NoteId {get; set;}
    public int TagId {get; set;}
} 

public class NoteBase
{
    public int NoteId {get; set;}
    public virtual ICollecton<TagBase> NoteTags {get; set;}
}

//then we inherit
public class OrderNoteTag : TagBase {}

public class OrderNote : NoteBase
{
    //Here we should pass the concrete type OrderNoteTag to NoteTags collection somehow
}

// Then we have method, where we should be able to pass OrderNote or ClientNote
public void ProcessNote(NoteBase note)
{
    foreach(var tag in note.NoteTags){...blah-blah-blah...}
}

Thanks in advance.

4
  • Did you try changing signature for ProcessNote to public void ProcessNote<TNote>(TNote note) where TNote : NoteBase? Commented Mar 9, 2016 at 12:04
  • @raderick, I need the common algorithm to save the notes, not depending of their type. They should come to the server at form of base class. And, again, the main problem is to inherit the navigation properties with the correct type, and this doesn't solve it. Commented Mar 9, 2016 at 12:09
  • I am not quite sure what you are trying to do here, probably you should also take a look at Visitor pattern. Commented Mar 9, 2016 at 12:19
  • What happens when you try the code you suggested? Do you get an error? Does it not compile? Commented Mar 10, 2016 at 5:19

1 Answer 1

1

Consider this approach, it is based on interfaces. Now you can use type INote<INoteTag> instead of NoteBase, look at the end of my answer, but instead of NoteTags property inside foreach loop you should use NoteTagsCustom() method, I hope that is not critical for you.

MODELS:

public interface INote<out T> where T : INoteTag
{
    int NoteId { get; set; }        
    IEnumerable<T> NoteTagsCustom();
}

public interface INoteTag
{
    int NoteTagId { get; set; }
    int TagId { get; set; }
}

public class OrderNote : INote<OrderNoteTag>
{
    [Key]
    public int NoteId { get; set; }
    public virtual ICollection<OrderNoteTag> NoteTags { get; set; }

    public IEnumerable<OrderNoteTag> NoteTagsCustom()
    {
        return NoteTags;
    }
}
public class OrderNoteTag : INoteTag
{
    [Key]
    public int NoteTagId { get; set; }
    [ForeignKey("OrderNote")]
    public int TagId { get; set; }
    public virtual OrderNote OrderNote { get; set; }
}

public class ClientNote : INote<ClientNoteTag>
{
    [Key]
    public int NoteId { get; set; }
    public virtual ICollection<ClientNoteTag> NoteTags { get; set; }

    public IEnumerable<ClientNoteTag> NoteTagsCustom()
    {
        return NoteTags;
    }
}
public class ClientNoteTag : INoteTag
{
    [Key]
    public int NoteTagId { get; set; }
    [ForeignKey("ClientNote")]
    public int TagId { get; set; }
    public virtual ClientNote ClientNote { get; set; }
}

IMPLEMENTATION:

//important: INote<INoteTag> instead of NoteBase!
public void ProcessNote(INote<INoteTag> note)
{
    //important: NoteTagsCustom() instead of NoteTags!
    foreach(var tag in note.NoteTagsCustom()){...blah-blah-blah...}
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, that's exactly what I was looking for. I kind of made it working using generic base class, but this approach seems to be better.
Not at all. Your approach with class inheritance is a good and the most obvious pattern, but at case of EF, it is not very suitable, because we must follow EF's specific rules and conventions connected with creating tables, relations between them and other features and all of it restrict us with range of applicable patterns.

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.