Entity Framework Code Чувствительность к первому регистру на строковых отношениях PK/FK

У меня есть довольно простое составное отношение один ко многим, определенное с использованием POCO/Fluent API, один столбец которого является строкой.

Я обнаружил, что данные в этом столбце в нашей базе данных являются несовместимыми с точки зрения случая, то есть "abb", "ABB" - это наша основная система ERP и снабжается различными источниками, которые в основном находятся вне нашего контроля.

Это приводит к проблемам с использованием кода EF в первую очередь при присоединении к связанным таблицам, так как EF беззвучно игнорирует объединение, когда случай PK/FK отличается, даже если SQL Profiler показывает правильный выполняемый SQL и возвращаемые результаты.

Я использую WCF, поэтому отложенная загрузка и создание прокси отключены, и я с нетерпением жду загрузки необходимых связанных сущностей с помощью Include. например.

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

Есть ли какие-либо решения для этого помимо внесения изменений в схему базы данных?

2 ответа

EF нечувствительное сравнение соединений

Привет у меня та же проблема (хотя не с остроумием код сначала, но с сгенерированной моделью)

Причина в том, что 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();

Это на самом деле работает, но, конечно, это слабое решение. Я придерживаюсь этого на некоторое время, поскольку я (или кто-то другой) предлагает лучшее решение.

Удачи!

Я нашел обходной путь, который вручную "зашивает" связь после того, как контекст извлек соответствующие строки из базы данных. В переводе на вашу проблему это будет примерно так:

//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();
}

Обратите внимание, как мы используем контекст.[DbSet].Локальное свойство, чтобы гарантировать, что мы делаем все "зашивание" в памяти без каких-либо дальнейших вызовов SQL. Я также выбираю участников без аудитов в качестве оптимизации производительности, чтобы мы не переоценивали работу ассоциации EF (в тех случаях, когда она работала). Но вы можете так же легко переназначить каждый "член" экземпляр.

Другие вопросы по тегам