c# – 使用Castle ActiveRecord插入许多行并忽略任何欺骗的推荐方法

c# – 使用Castle ActiveRecord插入许多行并忽略任何欺骗的推荐方法,第1张

概述我有一个webmethod,它将一堆食谱插入到数据库的队列中(以存储用户有兴趣烹饪的食谱,类似于NetFlix的电影队列).用户可以立即检查一堆食谱并排队.我有类似这样的代码: [WebMethod]public void EnqueueRecipes(SecurityCredentials credentials, Guid[] recipeIds){ DB.User user = 我有一个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)首先从数据库加载用户的整个队列并检查
首先列出.如果配方已存在,请继续
for循环.优点:没有不必要的sql插入发送到
数据库.缺点:较慢,特别是如果用户有一个大队列.
> 2)不要使用ActiveRecord而是传递整个recipeIDs数组
进入sql函数.此函数将检查每行是否存在
第一.优点:潜在的速度,让sql处理所有肮脏的工作.
缺点:打破ActiveRecord模式并需要新的DB代码,即
实施起来往往更难以维护和更昂贵.
> 3)每次循环后CreateAndFlush.基本上,不要运行这整个
在单个事务中循环.在添加时提交每一行
捕获sql错误并忽略.优点:低启动成本,但没有
需要新的sql后端代码.缺点:插入可能较慢
尽管用户可疑,但很多行都会立即进入数据库
会立刻提交十几个新的食谱.

还有Castle或NHibernate框架的其他小技巧吗?另外,我的sql后端是Postgresql 9.0.谢谢!

更新:

我在第一种方法中拍了一下它似乎工作得很好.它发生在我身上我不必加载整个队列,只需加载出来在recipeIDs中的队列.我相信我的foreach()循环现在是O(n ^ 2),这取决于List< GuID> :: Contains()的效率,但我认为这对于我将使用的大小来说可能是不错的.

//Check for dupesDB.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_recipeSELECT new_UserID,new_RecipeIDFROM   user_recipeWHERE  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_recipeSELECT disTINCT i.*  -- remove dupes from the insert candIDates themselvesFROM   ileft   JOIN user_recipe u USING (userID,recipeID)WHERE  u.userID IS NulL;

一次插入少数的解决方案

迈克评论说,临时表对于几条记录来说是一种过度杀伤力.

INSERT INTO user_recipeSELECT 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)    ) ileft   JOIN user_recipe u USING (userID,recipeID)WHERE  u.userID IS NulL;
总结

以上是内存溢出为你收集整理的c# – 使用Castle ActiveRecord插入许多行并忽略任何欺骗的推荐方法全部内容,希望文章能够帮你解决c# – 使用Castle ActiveRecord插入许多行并忽略任何欺骗的推荐方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1243084.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存