У меня есть веб-метод, который вставляет кучу рецептов в очередь в базе данных (для хранения рецептов, в которых пользователь заинтересован в приготовлении пищи, аналогично очереди фильмов NetFlix). Пользователь может отметить сразу несколько рецептов и поставить их в очередь. У меня есть код, похожий на этот:
[WebMethod]
public void EnqueueRecipes(SecurityCredentials credentials, Guid[] recipeIds)
{
DB.User user = new DB.User(credentials);
using (new TransactionScope(OnDispose.Commit))
{
foreach (Guid rid in recipeIds)
{
DB.QueuedRecipe qr = new DB.QueuedRecipe(Guid.NewGuid(), user, new DB.Recipe(rid));
qr.Create();
}
}
}
У меня есть уникальное ограничение на UserId / RecipeId, поэтому пользователь может поставить рецепт в очередь только один раз. Однако, если они выбирают рецепт, который уже находится в их очереди, я действительно не хочу беспокоить пользователя сообщением об ошибке, я просто хочу проигнорировать этот рецепт.
Приведенный выше код вызовет исключение SQL, если ограничение уникальности нарушено. Как лучше всего обойти это и просто игнорировать повторяющиеся строки. Мои текущие идеи:
продолжите
в
цикле for. Плюсы: в базу данных
не отправляются ненужные вставки SQL. Минусы: Медленнее, особенно если у пользователя большая очередь. Есть ли какие-нибудь другие хитрости с Castle или фреймворком NHibernate? Кроме того, мой SQL-сервер - PostgreSQL 9.0. Спасибо!
Обновление:
Я попытался использовать первый подход, и, похоже, он работает очень хорошо. Мне пришло в голову, что мне не нужно загружать всю очередь, только те, которые указаны в recipeIds. Я считаю, что мой цикл foreach ()
теперь O (n ^ 2) в зависимости от эффективности List
, но я думаю, что это, вероятно, подходит для размеры, с которыми я буду работать.
//Check for dupes
DB.QueuedRecipe[] dbRecipes = DB.QueuedRecipe.FindAll(Expression.In("Recipe",
(from r in recipeIds select new DB.Recipe(r)).ToArray()
));
List<Guid> existing = (from r in dbRecipes select r.Recipe.RecipeId).ToList();
using (new TransactionScope(OnDispose.Commit))
{
foreach (Guid rid in recipeIds)
{
if (existing.Contains(rid))
continue;
DB.QueuedRecipe qr = new DB.QueuedRecipe(Guid.NewGuid(), user, new DB.Recipe(rid));
qr.Create();
}
}