【发布时间】:2012-07-24 21:13:06
【问题描述】:
假设我有以下代码在 MVC 应用程序中将用户插入 MS Dynamics:
public bool CreateContact(string email)
{
if (crm.contacts.Count(x => x.Email == email) > 0)
return false; //Email already exist in the Crm. Skip
var contact = new contact {Email = email};
crm.AddTocontacts(contact);
crm.SaveChanges();
return true;
}
它非常适合阻止用户使用相同的电子邮件地址注册,直到最近我们遇到了 Dynamics 的主要性能问题。
显然,用户遇到了巨大的延迟,并且经常三次点击触发这段代码的按钮。
问题是,在 .SaveChanges() 在第一个请求中完成之前,.Count() 在不同的 Http 请求中同时触发。因此,我们看到的联系人使用相同的电子邮件地址。
虽然我已经从客户端添加了一个修复程序,但我想看看这是否也可以在服务器端完成。
什么是使这个线程安全的好策略?
编辑:
虽然在 CRM 上添加约束是这里许多人建议的最佳解决方案,但我目前无法实施该解决方案,因为早在发现此问题之前,CRM 中就已经存在重复项。显然,与 CRM 对话的应用程序不止一个。
由于对锁定和线程的经验很少,我最终做了以下事情:
internal static class ContactLock
{
internal static readonly object Locker = new object();
}
public bool CreateContact(string email)
{
lock(ContactLock.Locker)
{
if (crm.contacts.Any(x => x.Email == email))
return false; //Email already exist in the Crm. Skip
var contact = new contact {Email = email};
crm.AddTocontacts(contact);
crm.SaveChanges();
return true;
}
}
它通过了我的单元测试,似乎没有任何问题。
【问题讨论】:
-
在此工作时禁用该按钮?
-
Austin,是的,我已经在客户端这样做了。但我想看看我是否也可以从服务器上做到这一点。
-
对于 a) 意图和 b) 可能的优化,首选
.Any(x => x.Email == email)而不是Count(x => x.Email == email) > 0。 -
您使用的是 CRM 4 还是 CRM 2011?您是否使用直接数据库访问?我不知道 Linq 提供程序允许使用
Count。 -
@PeterMajeed:我们使用的是 CRM 4.0,您可以在这里下载一个 SDK:microsoft.com/en-us/download/details.aspx?id=38。它提供了一个代码生成工具,允许您使用 Linq 访问 CRM。这是一个写得不好的软件,应该避免 IMO。 (不能说 2011 年可能有所改善)
标签: c# asp.net-mvc multithreading dynamics-crm dynamics-crm-4