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

问题描述 投票:8回答:2

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

我有两张桌子

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抛出Null,当我将Registrations表中的UserName列的值更改为a而不是A时它可以工作。

这个Link谈论有点相似

这个Link另一个类似的问题

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

.net linq-to-sql c#-4.0 entity-framework-4
2个回答
11
投票

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

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

只有两种解决方案:

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

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


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强制执行大小写一致性。您可能需要事先通过将all设置为upper / lower来准备数据,如果使用alter table,可能需要删除并重新创建索引,约束等。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.