0

My solution should work well with: ASP.NET MVC 4, EF5, Code First, Visual Studio 2012 Express, SQL Server 2012 Express.

I need to store many tags with a place object. In another question it was suggested I use a List to achieve this:

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

ie

public List<String> Tags {get;set;}

If I just add that it doesn't get persisted in the database at all. How can I make it persist?

Thanks.

Update

This needs a many to many relationship - eg a place might be tagged Cafe and Cycle Shop. There are many cafe's and cycle shops.

   public class Place
   {
      public Place()
      {
         // Set default value of dateAdded to now
         DateAdded = DateTime.Now;
      }

      [ScaffoldColumn(false)]
      public virtual int PlaceID { get; set; }

      public virtual List<Tag> Tags { get; set; }

      [ScaffoldColumn(false)]
      [DisplayName("Date Added")]
      public virtual DateTime DateAdded { get; set; }

      [Required(ErrorMessage = "Place Name is required")]
      [StringLength(100)]
      public virtual string Name { get; set; }
      public virtual string URL { get; set; }

      [DisplayName("Contact Name")]
      public virtual string ContactName { get; set; }
      public virtual string Address { get; set; }
      public virtual string City { get; set; }

      [DisplayName("Post Code")]
      public virtual string PostCode { get; set; }
      public virtual string Website { get; set; }
      public virtual string Phone { get; set; }

      [EmailAddress(ErrorMessage = "Please enter valid email")]
      public virtual string Email { get; set; }
      public virtual string About { get; set; }
      public virtual string Image { get; set; }
   }
Community
  • 1
  • 1
niico
  • 11,206
  • 23
  • 78
  • 161

2 Answers2

5

How do you expect the Tags to be represented in the database? There is no native SQL Server type that EF maps to a List (it's more typical mapping is rows of a table to lists of objects) so you have to do some manipulation. If you want that to be a single cell (ie one field) then I would make it an nvarchar in the db and a string in code.

Then I would keep the list since it's easier to deal with in code and use the following LINQ query to transform the list into a comma separated list which will be a string, from there it can go into an nvarchar like any other string.

string csl = myList.Aggregate((c, n) => c + "," + n));

To go back to a list you just do;

List<string> = csl.Split(',').ToList();

Regardless of how you decide to represent your data it's not going to be as simple as just adding a list to a class. You'll have to put some thought into what makes the most sense for your application, this is just an idea to get you started since your question is a bit too vague to give a complete solution.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • Thanks - so it looks like it's between a comma separated string - or a separate tags table. Which would you recommend? – niico May 21 '13 at 06:15
  • @user2254951 that depends on the nature of tags. If there were an arbitrary limit or the expectation that a places tags list would never always be fairly short I would keep it on the places table as a csl. On the other hand, if it's boundless then it's necessary to have it on it's own table so the tags won't be limited by nvarchar(max). – evanmcdonnal May 21 '13 at 15:23
3

As evanmcdonnal said, EF can't map a plain list of strings to a database. A simple solution would be to create a Tag entity:

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

Then in your place entity, use a list of Tags:

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

//just a helper, not required
public void AddTag(string tagName)
{
    Tag tag = new Tag { Name = tagName };
    Tags.Add(tag);
}

The result will be a new Tags table in your database that contains a foreign key back to the Places table.

Brent
  • 545
  • 5
  • 7
  • This solution will likely be easier to query for many scenarios than stuffing all the tags in a single field. – AaronLS May 20 '13 at 23:10
  • 1
    As it's many to many I have added ICollection Tags {get;set;} to Places, and ICollection Places {get;set;} to Tags. – niico May 21 '13 at 10:19
  • 1
    @niico, your use of ICollection is probably wise and possibly a better choice than List so that you are not coding to an implementation. See: http://stackoverflow.com/questions/7655845/icollectiont-vs-listt-in-entity-framework – blins Jun 08 '13 at 16:54