asp.net MVC 4, tagging places - best practice (eg Pub, Store, Restaurant)

て烟熏妆下的殇ゞ 提交于 2019-12-08 04:13:50

问题


ASP.NET MVC 4 web app, EF 5, SQL Server 2012 Express, Visual Web Developer 2012 Express, Code First

I have a places object - I would like to add multiple tags to each place.

Is the best approach a comma separated string or related object?

Any design patterns or ways to manage the whole thing (adding, looking up, associating with a place etc)? Good performance is also of interest.

Tagging is done by administrators so speed / ease of implementation at the cost of a little ease of use is acceptable.

Thanks.


回答1:


Firstly, I don't think you need an object to represent a tag - assuming the tag is just a string.

What you should do is add a generic list property of strings to your entity like so:

public IList<string> Tags { get; set; }

Entity Framework will handle it just fine.

About the UI part, don't bother too much, these days everything is already implemented for you, Use jQuery Tag-It: http://aehlke.github.io/tag-it/

Update

Because EntityFramework gives a hard time with mapping list of string just create a simple class for it:

public class Tag
{
    public string Name { get; set; }
}

And use

public IList<Tag> Tags { get; set; }

Again, if not for EF's limitations (or if you use nhibernate) I would still recommend mapping to a list of strings just to avoid complexity (assuming speed is not the key)




回答2:


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:

  1. 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))
    
  2. 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.



来源:https://stackoverflow.com/questions/16653604/asp-net-mvc-4-tagging-places-best-practice-eg-pub-store-restaurant

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!