0

I have one table "Adverts" which stores basic info about adverts (eg: Name, Excerpt, Creation date...), and I need to store more detailed info in a separate table, But, here's my problem. Adverts can be different by type (sell, buy, rent, ...), category (residential, commercial, ...), so, detailed info is also different (eg: Commercial Advert don't need kitchen area property). I want to make few models which will describe detailed info for specific type or category

Here's my Adverts model:

[Table("Adverts_Adverts")]
public class Advert {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid AdvertId { get; set; }

    public virtual Metadata Metadata { get; set; }

    [Required]
    [DataType(DataType.Text)]
    public String Name { get; set; }

    [DataType(DataType.Html), AllowHtml]
    public String Content { get; set; }

    [ForeignKey("Section")]
    public Guid SectionId { get; set; }
    public virtual Section Section { get; set; }

    [ForeignKey("Category")]
    public Guid CategoryId { get; set; }
    public virtual Category Category { get; set; }

    [ForeignKey("Type")]
    public Guid TypeId { get; set; }
    public virtual Type Type { get; set; }

    public Decimal Price { get; set; }

    [DataType("Enum")]
    public Currency Currency { get; set; }

    [ForeignKey("Details")]
    public Guid DetailsId { get; set; }
    public virtual ?????????? Details { get; set; }

    [ForeignKey("User")]
    public String UserId { get; set; }
    public virtual User User { get; set; }

    [ReadOnly(true)]
    [DataType(DataType.DateTime)]
    public DateTime Added { get; set; }

    [ReadOnly(true)]
    [DataType(DataType.DateTime)]
    public DateTime Updated { get; set; }

    public Int32 Views { get; set; }

    [ReadOnly(true)]
    public Status Status { get; set; }

    ...
}

here's my detailed info model for residential adverts:

[Table("Adverts_Details")]
public class ResidentialDetails {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid DetailsId { get; set; }

    [ForeignKey("Advert")]
    public Guid AdvertId { get; set; }
    public virtual Advert Advert { get; set; }

    [Required]
    public Int32 Storeys { get; set; }

    [Required]
    public Int32 Floor { get; set; }

    [Required]
    public Int32 Rooms { get; set; }

    [Required]
    public Decimal TotalArea { get; set; }

    [Required]
    public Decimal LivingArea { get; set; }

    [Required]
    public Decimal KitchenArea { get; set; }

    ...
}

and this may be for commercial adverts:

[Table("Adverts_Details")]
public class CommercialDetails {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid DetailsId { get; set; }

    [ForeignKey("Advert")]
    public Guid AdvertId { get; set; }
    public virtual Advert Advert { get; set; }

    [Required]
    public Int32 OfficesCount { get; set; }

    [Required]
    public Int32 Floor { get; set; }

    [Required]
    public Decimal TotalArea { get; set; }

    ...
}

So, how can I access both, ResidentialDetails and CommercialDetails, data within advert's property "Details"?

(Thank in advance)

2
  • 1
    The way you describe what you're after is unclear. Perhaps show us an example of what you'd like to be able to do with your code, and explain what part of it you're confused about? Commented Jun 26, 2014 at 19:10
  • sorry for my english, I added an example Commented Jun 26, 2014 at 19:54

1 Answer 1

1

This is an architecture problem, which is hard to answer without a complete understanding of your business rules. I can give you some general advice that will hopefully help you along.

As much as possible, remove complexity. I'm not sure what a "kitchen area property" is, but can you generalize it at all? Based upon context, you can call it something different, use it differently, etc. but if it's just a text field, then you can repurpose it in other contexts. Maybe for a residential advert it's "kitchen area" while maybe for commercial it's "break room area". (I really have no idea what this property is for, but I'm just trying to make the point that the same property can have a similar but slightly different meaning in different contexts).

If you can't generalize, then you'll need to start working on inheritance strategies. Create an object graph. How are these types and categories of adverts related. How are they different. Which ones are supergroups of others, etc.? Again, I don't know anything about the business rules at play, but maybe you need classes like Advert, ResidentialAdvert : Advert and CommercialAdvert : Advert. Then, you can add additional properties to these subclasses as necessary.

You'll also need to decide on a relational strategy. By default, EF will implement simple inheritance as STI (single-table inheritance, aka table per hierarchy or TPH for short). In other words, with the classes above, you would end up with an Adverts table with a Discriminator column. The value for this column would be one of "Advert", "ResidentalAdvert", or "CommercialAdvert", indicating which class should be instantiated, but all of the columns for all of the subclasses would reside in the same table. The benefit is that no joins are necessary, but the detriment is that all additional columns on your subclasses must be nullable or have default values. Other possible strategies would include, table per type (TPT), a compositional strategry, or table per concrete type (TPC), where every subtype gets its own unique table with all the fields from all supertypes.

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

1 Comment

tnx Chris, "you would end up with an Adverts table with a Discriminator column" I saw this in Identity 2.x I'll try... but need to learn more around ;)

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.