ASP.NET MVC 4 Web 应用程序、EF 5、SQL Server 2012 Express、Visual Web Developer 2012 Express、代码优先
我有一个地点对象 - 我想为每个地点添加多个标签。
最好的方法是逗号分隔的字符串还是相关对象?
任何设计模式或管理整个事物的方法(添加、查找、与地点关联等)?良好的性能也令人感兴趣。
标记由管理员完成,因此速度/易于实施以牺牲一点易用性为代价是可以接受的。
谢谢。
ASP.NET MVC 4 Web 应用程序、EF 5、SQL Server 2012 Express、Visual Web Developer 2012 Express、代码优先
我有一个地点对象 - 我想为每个地点添加多个标签。
最好的方法是逗号分隔的字符串还是相关对象?
任何设计模式或管理整个事物的方法(添加、查找、与地点关联等)?良好的性能也令人感兴趣。
标记由管理员完成,因此速度/易于实施以牺牲一点易用性为代价是可以接受的。
谢谢。
首先,我认为你不需要一个对象来表示一个标签——假设标签只是一个字符串。
您应该做的是将字符串的通用列表属性添加到您的实体,如下所示:
public IList<string> Tags { get; set; }
实体框架会处理得很好。
关于 UI 部分,不要太在意,这几天一切都已经为你实现了,使用 jQuery Tag-It:http ://aehlke.github.io/tag-it/
更新
因为 EntityFramework 很难使用字符串的映射列表,只需为它创建一个简单的类:
public class Tag
{
public string Name { get; set; }
}
并使用
public IList<Tag> Tags { get; set; }
同样,如果不是因为 EF 的限制(或者如果您使用 nhibernate),我仍然建议映射到字符串列表以避免复杂性(假设速度不是关键)
无论哪种方式,您都可以真正处理它;它只取决于你想要什么以及你想要完成什么。作为逗号分隔的字符串或IList<string>
,它至少是可搜索的,但仅此而已。您也很难对标签进行任何形式的标准化(即不同的地方可能有“Chinese Buffet”、“chinese”、“chinese Buffet”、“chinese-buffet”等)。
最稳健的方法是Tag
与 具有 M2M 关系的实际实体Place
。这样,您可以通过使名称成为唯一列并执行先发制人的重复数据删除查询(即使用条目:“中文”、“您的意思是'中文'吗?”等)来获得相当程度的规范化。
拥有一个Tag
实体还可以让您轻松地进行自动完成查询,因为您将在一个地方查找所有标签或以某个字符开头的标签。用逗号分隔的字符串几乎不可能实现这一点,因为它需要首先聚合所有这些字符串(以及所有不同类型的对象),然后在最终返回列表之前解析出唯一标签。
更新
我不知道任何与 MVC 相关的现有标签项目。Google 应该能够提供帮助或仅在 Visual Studio 中的 NuGet 包管理器中进行搜索。
但是,这很容易自己推出。
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
}
这里唯一困难的部分是,为了让 EF 将关系识别为 M2M,关系的双方都需要有一个指向对方的导航属性。你有两个选择:
继续往两边添加导航属性。因此,Tag
您将添加以下行:
public virtual ICollection<Place> Places
这并没有什么“错误”,如果您希望能够轻松查找特定标签的位置,实际上可能需要这样做。但是,您仍然可以在没有导航属性的情况下获取该信息,即:
db.Places.Where(m => m.Tags.Contains(someTag))
使用 anEntityTypeConfiguration
明确告诉 EF 这是一个 M2M。我通常遵循的模式是在我的实体中创建一个“映射”类:
public class Place
{
...
public class PlaceMapping : EntityTypeConfiguration<Place>
{
public PlaceMapping()
{
HasMany(m => m.Tags).WithMany();
}
}
}
然后,在您的 DbContext 中:
public override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Place.PlaceMapping());
// Any other configurations added here the same way
}
这只是我遵循的模式以保持事物井井有条,EntityTypeConfiguration
只要您可以从 DbContext 中引用它,您就可以将其放置在您喜欢的任何位置。