外键上的实体框架nvarchar案例敏感性
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了外键上的实体框架nvarchar案例敏感性相关的知识,希望对你有一定的参考价值。
我有相当简单的表格结构如下,发出的声音对我来说很奇怪。虽然我选择了解决它,但想听听专家的意见。
我有两张桌子
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另一个类似的问题
请分享您的答案为什么会出现这种情况,我的数据库的排序规则不区分大小写。你遇到过类似的事吗?
这里的问题是你的数据库不区分大小写,但CLR(.NET)不是,而且与数据库不同,它不能全局切换到不区分大小写的模式 - 你必须按比较进行。
当您调用item.User1.LastName
时,EF将触发延迟加载 - 在数据库中执行附加查询以加载相关用户但是当用户实现时,EF将开始修复并验证其关系模型,这就出现了问题 - 它将字符串与区分大小写进行比较根据这个设置,a
不等于A
,因此你加载的User
实体不是你的Registration
实体的关系。因此,EF不会修复User1
属性,它将保持为null。在这种情况下访问LastName
会抛出NullReferenceException
。
只有两种解决方案:
- 修复您的数据库并确保此案例差异不会再次出现在您的数据中
- 如果您在项目的开头,或者您完全控制数据库重新设计它。
NVarChar
主键和外键都是糟糕的数据库设计。
如果这些选择都不适合您,则应避免将EF与此类数据库一起使用。
@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可用,因此根据您的具体情况,其他一个区分大小写的选项可能更合适。
以上是关于外键上的实体框架nvarchar案例敏感性的主要内容,如果未能解决你的问题,请参考以下文章
Criteria API JPA Hibernate:外键上的不同选择