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

У меня есть довольно простое составное отношение один ко многим, определенное с использованием 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 ]

2 голосов
/ 28 ноября 2011

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

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

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

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

Удачи!

0 голосов
/ 24 сентября 2012

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

//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 (в тех случаях, когда она работала). Но вы также можете легко переназначить каждый экземпляр "member".

...