c# – 使用Castle ActiveRecord插入许多行并忽略任何欺骗的推荐
我有一个webmethod,它将一堆食谱插入到数据库的队列中(以存储用户有兴趣烹饪的食谱,类似于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异常.解决这个问题的最佳方法是什么,只需忽略重复的行.我目前的想法是: > 1)首先从数据库加载用户的整个队列并检查 还有Castle或NHibernate框架的其他小技巧吗?另外,我的SQL后端是PostgreSQL 9.0.谢谢! 更新: 我在第一种方法中拍了一下它似乎工作得很好.它发生在我身上我不必加载整个队列,只需加载出来在recipeIds中的队列.我相信我的foreach()循环现在是O(n ^ 2),这取决于List< Guid> :: Contains()的效率,但我认为这对于我将使用的大小来说可能是不错的. //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(),new DB.Recipe(rid)); qr.Create(); } } 解决方法
您可以使用单个SQL语句执行此操作:
INSERT INTO user_recipe SELECT new_UserId,new_RecipeId FROM user_recipe WHERE NOT EXISTS ( SELECT * FROM user_recipe WHERE (UserId,RecipeId) = (new_UserId,new_RecipeId) ); SELECT仅返回该行(如果该行尚不存在),因此仅在此情况下插入该行. 批量插入的解决方案 如果您要一次插入一长串食谱,您可以: CREATE TEMP TABLE i(userId int,recipeid int) ON COMMIT DROP; INSERT INTO i VALUES (1,2),(2,4),7),43),(23,113),(223,133); INSERT INTO user_recipe SELECT DISTINCT i.* -- remove dupes from the insert candidates themselves FROM i LEFT JOIN user_recipe u USING (userid,recipeid) WHERE u.userid IS NULL; 一次插入少数的解决方案 迈克评论说,临时表对于几条记录来说是一种过度杀伤力. INSERT INTO user_recipe SELECT i.* FROM ( SELECT DISTINCT * -- only if you need to remove possible dupes FROM ( VALUES (1::int,2::int),3),4) -- dupe will be removed,133) ) i(userid,recipeid) ) i LEFT JOIN user_recipe u USING (userid,recipeid) WHERE u.userid IS NULL; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |