我的LinqToSql模型上有一个非常有趣的问题。在我的一些表上,我有对其他表的引用,在LinqToSql中,这是由EnitiyRef类表示的,当你试图访问引用表时,LinqToSql将从数据库加载引用。
在我的开发机器上,一切都很好(引用加载得很好),但昨晚我将更改后的上传到了我们的生产服务器,并在尝试访问表上的引用时开始获得NullReferenceException。
样本代码:
var sale = db.Sales.Single(s => s.ID == 1);
string username = sale.User.Name; // User is a reference to a User table
// LinqToSql will automatically load the
// row and access the fields i need.
// On my server the sale.User throws an exception that its null (User) but the user
// is definitly in the database (there is even a FK constraint from Sale to User)
一开始我以为我的DataContext已经GC了,但我仔细检查了所有内容,没有结果(此外,它在我的盒子上也有效)。
(服务器和我的盒子上的一切都是一样的,相同的dll,相同的数据库架构等等。)(我实际上把整个DBF文件复制到了我的服务器上,所以它是完全相同的模式)
您是否打开了上下文登录,并将开发框上的结果与生产框上的进行了比较?
如果将源代码移动到生产服务器并在那里进行编译,请尝试为DataContext重新生成生成的源代码。您可以通过从DataContext源文件的上下文菜单运行"运行用户定义的工具"来实现这一点。
如果两者共享相同的二进制文件,请确保两个数据库中的数据库定义完全相同。一个小的差异,比如一列在生产服务器上可以为null,但在devbox上不能为null,可以产生所有的差异。
为了找到并解决这样的问题,它将有助于对数据库进行堆栈跟踪和分析。
这个问题可能是一个安全问题。您是否尝试在Management Studio中使用与应用程序使用的凭据相同的凭据登录,并在表上进行选择。
这至少会让你了解安全性或linq问题。
检查DataContext生存期。可能有过时的缓存在工作
例如:
- 上下文1:加载ID为==1的销售。检查其User属性并观察null User
- 上下文2:加载ID==1的销售。通过添加新用户来修改"用户"属性。提交
- 上下文1:加载ID为==1的销售。检查其User属性。是的,仍然为null(它已缓存!!)
一种可能性是DBML使用的连接字符串仍然指向生产以外的数据库服务器。
每当在ASPX页面中直接使用LinqDataSource时,就会发生这种情况,因此DataContext使用默认构造函数,该构造函数指向基于上次开发人员用于导入DBML的数据库的连接字符串。
我们所做的是创建一个从生成的DataContext继承的DataContext对象,并使用web.config中的正确连接字符串覆盖默认构造函数。