外键上的实体框架nvarchar案例敏感性

时间:2012-03-17 16:25:39

标签: .net linq-to-sql c#-4.0 entity-framework-4

我有相当简单的表格结构如下,对我来说发出的声音很奇怪。虽然我选择解决它,但想听取专家的意见。

我有两张桌子

Users
UserName nvarchar(250) Primary Key
FirstName nvarchar(50)
LastName  nvarchar(50)

Registrations
Id BigInt PrimaryKey
User nvarchar(250) - Foreign to Users Table
Date - DateTime

Data I have is as follows.
Users
UserName FirstName LastName
a        Small     A 
b        Small     B

Registrations
Id       User      Date
1        A         1/1/12
2        B         1/1/12

请注意这里的用户案例是它在SQL中有效,它接受。

现在有趣的部分。我生成了EDMX,.Net 4.0,现在我执行了这段代码。

 using (EFTestEntities context = new EFTestEntities())
            {
                var item = context.Registrations.Where(id => id.Id == 1).FirstOrDefault();
                Response.Write(item.User1.LastName);
            }

它只是打破空指针异常User1抛出空,当我将注册表中的UserName列的值更改为 a 而不是 A 时,它可以正常工作。

这个Link谈论有些相似

Link另一个类似问题

请分享您的答案为什么会出现这种情况,我的数据库的排序是不区分大小写的。你有没有遇到类似的事情?

2 个答案:

答案 0 :(得分:11)

这里的问题是您的数据库不区分大小写,但CLR(.NET)不是,并且与数据库不同,它不能全局切换到不区分大小写的模式 - 您必须按比较进行。

当您调用item.User1.LastName EF将触发延迟加载时 - 在数据库中执行附加查询以加载相关用户但是当用户实现时,EF将开始修复并验证其关系模型,这就出现了问题 - 它将字符串与区分大小写进行比较,因此根据此设置,a不等于A,因此您加载的User实体不是您的Registration实体的关系。因此,EF不会修复User1属性,它将保持为空。在这种情况下访问LastName会抛出NullReferenceException

只有两种解决方案:

  • 修复您的数据库并确保此案例差异不会再次出现在您的数据中
  • 如果您在项目的开头,或者您完全控制数据库重新设计它。 NVarChar主键和外键是糟糕的数据库设计。

如果这些选择都不适合您,则应避免将EF与此类数据库一起使用。

答案 1 :(得分:0)

@Ladislav很好地描述了这个问题,但是有些人可能会使用另一种方法。表中的各个列可以区分大小写,因此它们的行为与.Net相同;

Users
UserName nvarchar(250) collate Latin1_General_CS_AS Primary Key
FirstName nvarchar(50)
LastName  nvarchar(50)

Registrations
Id BigInt PrimaryKey
User nvarchar(250) collate Latin1_General_CS_AS - Foreign to Users Table
Date - DateTime

请注意添加到列定义中的collate。现在(假设您已定义外键),数据库将仅针对两个表之间的UserName强制使用大小写一致性。您可能需要事先通过将所有设置都设置为上/下来准备数据,并且如果使用alter table,则可能需要删除并重新创建索引,约束等。

这比尝试在数据库级别更改排序规则的影响要低得多,但仍需要进行一些思考和测试,因为根据其他有效的排序规则,您可能会遇到需要处理的排序规则冲突。

有许多collations可用,因此根据您的情况,其他区分大小写的选项之一可能更适合。