字符串 PK/FK 关系上的实体框架代码优先区分大小写

发布于 2024-12-04 14:47:32 字数 451 浏览 1 评论 0原文

我有一个使用 POCO/Fluent API 定义的相当简单的复合一对多关系,其中一列是一个字符串。

我发现我们数据库中此列中的数据在大小写方面不一致,即“abb”、“ABB”——这是我们的主要 ERP 系统,由各种来源提供,这些来源主要超出我们的控制范围。

这会导致在联接到相关表时首先使用 EF 代码出现问题,因为当 PK/FK 的大小写不同时,EF 会默默地忽略联接,即使 SQL Profiler 显示正在执行的正确 SQL 并返回结果也是如此。

我正在使用 WCF,因此关闭了延迟加载和代理创建,并且急于使用 Include 加载所需的相关实体。例如。

var member = context.Member.Include(m => m.Audits).First(m => m.Id == id); 

除了修改数据库模式之外,还有其他解决方案吗?

I have a fairly simple composite one to many relationship defined using POCO/Fluent API, one column of which is a string.

I've discovered that the data in this column in our database is inconsistent in terms of case ie 'abb', 'ABB' - this is our main ERP system and is fed by a variety of sources which are mainly beyond our control.

This is leading to problems using EF code first when joining to related tables as the join is silently ignored by EF when the case of PK/FK is different even though SQL Profiler shows the correct SQL being executed and results returned.

I'm using WCF so have lazy loading and proxy creation turned off and am eager loading required related entities using Include. eg.

var member = context.Member.Include(m => m.Audits).First(m => m.Id == id); 

Are there any solutions to this outside of amending the database schema?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

习ぎ惯性依靠 2024-12-11 14:47:32

EF Insensitive join Comparison

嗨,我遇到了同样的问题(虽然不是首先使用代码,而是使用生成的模型)

原因是EF对关键字段进行了区分大小写的比较,并且没有找到相关对象。

我猜问题出在“EDM 关系经理”上,也许有可能覆盖这种行为。

我找到了一个简单的解决方法:将相关属性小写:

    [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.String id
    {
        get
        {
            return _id.ToLower(); // **<- here**
        }
        set
        {
            if (_id != value)
            {
                OnidChanging(value);
                ReportPropertyChanging("id");
                _id = StructuralObject.SetValidValue(value, false);
                ReportPropertyChanged("id");
                OnidChanged();
            }
        }
    }
    private global::System.String _id;
    partial void OnidChanging(global::System.String value);
    partial void OnidChanged();

它确实有效,但是,当然,这是一个蹩脚的解决方法。
我会坚持一段时间,直到我(或某人)提出更好的解决方案。

祝你好运!

EF Insensitive join comparison

Hi I'm having the same problem (although not wit code first, but with a generated model)

The cause is that EF makes a case-sensitive comparison of the key fields, and it doesn'n find the related objects.

I'm guessing the problem lies in the "EDM Relationship Manager" and maybe there's a possibility of overriding this behavior.

I found a simple workaround for this: lower casing the related properties:

    [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.String id
    {
        get
        {
            return _id.ToLower(); // **<- here**
        }
        set
        {
            if (_id != value)
            {
                OnidChanging(value);
                ReportPropertyChanging("id");
                _id = StructuralObject.SetValidValue(value, false);
                ReportPropertyChanged("id");
                OnidChanged();
            }
        }
    }
    private global::System.String _id;
    partial void OnidChanging(global::System.String value);
    partial void OnidChanged();

It actually works, but, of course, it's a lame workoround.
I'm sticking to it for a while util I (or somebody) comes out with a better solution.

Good Luck!

原来分手还会想你 2024-12-11 14:47:32

我想出了一个解决方法,在上下文从数据库中检索到适当的行后,手动“缝合”关联。转化为你的问题将是这样的:

//Your original query
var members = context.Member.Include(m => m.Audits).First(m => m.Id == id); 

//The "stitch up" code that should probably be moved to a method of the data context.
var membersWithoutAudits = context.Members.Local.Where(m => !m.Audits.Any()).ToList();
foreach (var nextMember in membersWithoutAudits) {
  //Now we can populate the association using whatever logic we like
  nextMember.Audits = context.Audits.Local.Where(a => a.MemberId.ToLower() == nextMember.Id.ToLower()).ToList();
}

注意我们如何使用 context.[DbSet].Local 属性来确保我们在内存中完成所有“缝合”而不进行任何进一步的 SQL 调用。我还获取未经审核的成员作为性能优化,因此我们不会重新执行 EF 协会的工作(在它确实有效的情况下)。但是您可以轻松地重新映射每个“成员”实例。

I came up with a workaround that manually "stitches up" the association after the context has retrieved the appropriate rows from the database. Translated to your problem it would be along these lines:

//Your original query
var members = context.Member.Include(m => m.Audits).First(m => m.Id == id); 

//The "stitch up" code that should probably be moved to a method of the data context.
var membersWithoutAudits = context.Members.Local.Where(m => !m.Audits.Any()).ToList();
foreach (var nextMember in membersWithoutAudits) {
  //Now we can populate the association using whatever logic we like
  nextMember.Audits = context.Audits.Local.Where(a => a.MemberId.ToLower() == nextMember.Id.ToLower()).ToList();
}

Notice how we use the context.[DbSet].Local property to ensure that we do all the "stitch up" in memory without making any further SQL calls. I also fetch the members without audits as a performance optimization so we are not re-doing the work of EF's association (in the cases where it did work). But you could just as easily remap every "member" instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文