You can really handle it either way; it just depends on what you want and what you're trying to accomplish. As a comma-delimited string or an IList<string>
, it would at least be searchable, but not much more than that. You'd also have a very hard time doing any sort of normalization on the tags (i.e. different places might have "Chinese Buffet", "chinese", "chinese buffet", "chinese-buffet", etc.).
The most robust method would be an actual Tag
entity with a M2M relationship with Place
. With that you can get a fair degree of normalization from making the name a unique column, and performing pre-emptive de-duplication queries (i.e. With entry: "chinese", "Did you mean 'Chinese'?", etc.).
Having a Tag
entity also lets you easily do autocomplete queries, as you'll have one place to look up all tags or tags starting with a certain character(s). A comma-delimited string would be near impossible to implement this with as it would requiring aggregating all those strings (and across all different types of objects) first and then parsing out unique tags before finally returning a list.
UPDATE
I don't know of any existing tag related projects for MVC off the top of my head. Google should be able to help or just search in NuGet Package Manager in Visual Studio.
However, this is pretty simple to roll your own.
public class Tag
{
public int TagId { get; set; }
public string Name { get; set; }
// If your tags will be more freeform (and not necessarily URL compatible)
public string Slug { get; set; }
}
public class Place
{
...
public virtual ICollection<Tag> Tags
}
The only difficult part here is that in order for EF to recognize a relationship as M2M, both sides of the relationship need to have a navigation property pointing to the other. You have two options:
Go ahead and add navigation properties to both sides. So, in Tag
you would add the line:
public virtual ICollection<Place> Places
There's nothing "wrong" with this and in fact may be desired if you want to be able to easily look up places for a particular tag. However, you can still get that information without a navigation property, i.e.:
db.Places.Where(m => m.Tags.Contains(someTag))
Use an EntityTypeConfiguration
to explictly tell EF that this is an M2M. The pattern I normally follow for this is to create a "Mapping" class within my entity:
public class Place
{
...
public class PlaceMapping : EntityTypeConfiguration<Place>
{
public PlaceMapping()
{
HasMany(m => m.Tags).WithMany();
}
}
}
Then, in your DbContext:
public override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Place.PlaceMapping());
// Any other configurations added here the same way
}
This is just the pattern I follow to keep things organized, you can place your EntityTypeConfiguration
wherever you like as long as you can reference it from your DbContext.