我在名为Users
的数据库中有一个表Users ------ ID (PK, Identity) Username (Unique Index)
我在Username表上设置了一个唯一索引以防止重复。然后,我将通过集合枚举并在数据库中为每个项目创建新用户。
我想要做的只是插入一个新用户并在违反唯一键约束时忽略该异常(因为在这种情况下它显然是重复记录)。这是为了避免必须制作哪里不存在类型的查询。
首先,这会更高效还是我的插入代码应该检查重复项?我更多地了解具有该逻辑的数据库,因为这可以防止任何其他类型的客户端插入重复数据。
我的另一个问题与LINQ To SQL有关。我有以下代码:
public class TestRepo
{
DatabaseDataContext database = new DatabaseDataContext();
public void Add(string username)
{
database.Users.InsertOnSubmit(new User() { Username = username });
}
public void Save()
{
database.SubmitChanges();
}
}
然后我迭代一个集合并插入新用户,忽略任何异常:
TestRepo repo = new TestRepo();
foreach (var name in new string[] { "Tim", "Bob", "John" })
{
try
{
repo.Add(name);
repo.Save();
}
catch { }
}
第一次运行时,我在表中有三个用户。如果我删除第二个并再次运行此代码,则不会插入任何内容。我期望第一个插入失败,异常,第二个插入成功(因为我刚从数据库中删除该项),第三个插入失败。
似乎正在发生的事情是,一旦抛出SqlException(即使循环继续迭代),所有下一次插入都会失败 - 即使表中没有可能导致唯一违规的行。 / p>
任何人都能解释一下吗?
P.S。我能找到的唯一解决方法是每次在插入之前实例化repo,然后它完全按照例外工作 - 表明它与LINQ To SQL DataContext有关。
感谢。
答案 0 :(得分:1)
在第二次插入时,dataContext将再次尝试插入第一个对象,因为它位于此dataContext的标识映射中(您希望插入'Tim'仍然未决 - 在第一次捕获后)。
在第一个循环中,您插入'Tim' 第二个'蒂姆'和'鲍勃' 在第三'蒂姆','鲍勃'和'约翰' 所以你不是只在第二个循环中插入'Bob',这就是失败的原因。
您可以尝试从cach中的DataContext中删除失败的名称,但无论如何,在一个数据上下文中多次提交都是非常糟糕的主意(我被烧毁了)。
答案 1 :(得分:0)
尝试在测试运行之间调用DataContext上的DataContext.Refresh
。
我认为你正忙于Linq-to-Sql的内部缓存,这就是重新创建DataContext作为解决方法的原因,当你新建DataContext时,新对象的缓存将为空。
答案 2 :(得分:0)
你应该使用try catch技巧检查是否存在。
foreach (var name in new string[] { "Tim", "Bob", "John" })
{
var u = from users in db.Users
where users.username == name
select users;
if (u.Count() == 0)
{
User user = new User();
user.name = name;
db.Users.InsertOnSubmit(user);
db.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
}
}
答案 3 :(得分:0)
很难说你的方法是否“效率更高”。这取决于您获得重复帐户的频率。如果您的费率非常高,那么您就会失去速度,因为处理异常可能需要更多时间,而不是检查是否存在记录。
如果要最大化速度,请创建一个存储过程以检查并插入(如果它不在数据库中)。