【发布时间】:2011-08-13 18:04:49
【问题描述】:
我有一个图片网站,用户可以在其中标记照片,就像您可以在 Stackoverflow 上标记问题一样。
我有以下表格:
Images [ID, URL, etc]
Tags [ID, TagName]
ImageTag [TagID, ImageID]
我想写一个带有签名的方法:
public void UpdateImageTags(int imageId, IEnumerable<string> currentTags)
此方法将执行以下操作:
- 在当前标签中创建标签表中尚不存在的任何新标签。
- 获取图像的旧 ImageTag。
- 删除所有不再存在于 currentTag 中的 ImageTag
- 在 currentTags 和 oldTags 之间添加任何新的 ImageTag。
这是我对该方法的尝试:
public void UpdateImageTags(int imageId, IEnumerable<string> currentTags)
{
using (var db = new ImagesDataContext())
{
var oldTags = db.ImageTags.Where(it => it.ImageId == imageId).Select(it => it.Tag.TagName);
var added = currentTags.Except(oldTags);
var removed = oldTags.Except(currentTags);
// Add any new tags that need created
foreach (var tag in added)
{
if (!db.Tags.Any(t => t.TagName == tag))
{
db.Tags.InsertOnSubmit(new Tag { TagName = tag });
}
}
db.SubmitChanges();
// Delete any ImageTags that need deleted.
var deletedImageTags = db.ImageTags.Where(it => removed.Contains(it.Tag.TagName));
db.ImageTags.DeleteAllOnSubmit(deletedImageTags);
// Add any ImageTags that need added.
var addedImageTags = db.Tags.Where(t => added.Contains(t.TagName)).Select(t => new ImageTag { ImageId = imageId, TagId = t.TagId });
db.ImageTags.InsertAllOnSubmit(addedImageTags);
db.SubmitChanges();
}
}
但是,这行失败:
db.ImageTags.DeleteAllOnSubmit(deletedImageTags);
出现错误:
在查询的 LINQ to SQL 实现中不能使用本地序列 除包含运算符之外的运算符。
有没有更简单的方法可以处理在 LINQ to SQL 中添加新标签、删除旧 ImageTags、添加新 ImageTags 的操作?
【问题讨论】:
-
数据库中有多少个标签?这将是“从数据库中读取所有标签并进行比较”与“每个项目的查询”之间的关键因素
-
@Marc Gravell,可能会有数千个标签。也许超过 10k,少于 50k?总猜测。它仍在开发中,我们已经有将近一千个了。
-
那不能在服务器的TSQL中做吗?
-
@Mac Gravell,是的,它可以。 linq to sql 是否有一些限制会阻止它有效地执行此操作?
-
@Viktor 有限制吗?水合所有这些对象、进行更改并将它们推回的开销明显高于在数据库级别发出单个更新语句而无需通过网络传递所有这些数据。将其放入存储过程中,如果需要,可以使用 LINQ 调用该过程。
标签: c# linq-to-sql tagging