2015-07-08 3 views
1

Возможно ли реализовать условие условного соединения в Entity Framework 6? В частности, INNER JOIN ON (логическое условие 1) ИЛИ (логическое условие2).Возможно реализовать условие условного соединения - JOIN ON condition1 ИЛИ condition2?

Код ниже работает, но дважды вызывает базу данных. Можно ли объединить его в один звонок?

Существует внешний ключ отношения, которые связывает FirmFeatures.FeatureId с Nullable FirmParameters.FeatureId

var dbContext = new MyEntities(); 
var feature = dbContext.FirmFeatures 
    .Where(f => f.FeatureId == featureId) 
    .First(); 

var parameters = dbContext.FirmParameters.AsQueryable(); 

parameters = feature.IsDbTable 
    ? parameters.Where(p => p.FeatureId == null) 
    : parameters.Where(p => p.FeatureId == featureId); 

var list = parameters.ToList() 

SQL, вызов будет выглядеть примерно так:

SELECT feature.*, parameter.* 
FROM [FirmFeature] AS feature 
INNER JOIN [FirmParameter] AS parameter 
    ON (feature.IsDbTable = 0 AND feature.FeatureId = parameter.FeatureId) OR (feature.IsDbTable = 1 AND parameter.FeatureId IS NULL) 
WHERE feature.[FeatureId] = 3 

Эта модель базы данных заемных средств в первую очередь.

Я новичок в платформе Entity Framework.

Редактировать 2: Я надеюсь, что в результате этого будет создан объект объектов и объект параметров, загруженный из базы данных.

EDIT: В соответствии с просьбой, вот модели:

{ 
    public FirmFeature() 
    { this.FirmParameters = new HashSet<FirmParameter>(); } 

    public byte FeatureId { get; set; } 
    public bool IsDbTable { get; set; } 
    ... 
    public virtual ICollection<FirmParameter> FirmParameters { get; set; } 
} 

public partial class FirmParameter 
{ 
    public byte ParameterId { get; set; } 
    public Nullable<byte> FeatureId { get; set; } 
    ...  
    public virtual FirmFeature FirmFeature { get; set; } 
    public virtual FirmParameter FirmParameter1 { get; set; } 
    public virtual FirmParameter FirmParameter2 { get; set; } 
} 
+0

могли бы вы поделиться C# дб схемы? – czifro

+0

Вам нужно показать свои сущности. Кроме того, нет причин добавлять 'AsQueryable()' после 'dbContext.FirmParameters', который уже является' IQueryable'. – haim770

+0

Без этого компиляция не удалась. Невозможно неявно преобразовать тип «System.Linq.IQueryable » в «System.Data.Entity.DbSet ». Явное преобразование существует (вы пропускаете листинг?) @ Haim770 – Hoppe

ответ

0

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

Что-то вроде:

var query = from feature in dbContext.FirmFeatures 

      join parameter0 in dbContext.FirmParameters 
       on new { IsDbTable = feature.IsDbTable, FeatureId = feature.FeatureId } equals new { IsDbTable = false, FeatureId = parameter0.FeatureId ?? 0 } 
       into left_parameter_0 
       from parameter_0 in left_parameter_0.DefaultIfEmpty() 

      join parameter1 in dbContext.FirmParameters 
       on new { IsDbTable = feature.IsDbTable, FeatureId = (byte?)null } equals new { IsDbTable = true, FeatureId = parameter1.FeatureId } 
       into left_parameter_1 
       from parameter_1 in left_parameter_1.DefaultIfEmpty() 

select new { Feature = feature, Parameter = parameter_0 != null ? parameter_0 : parameter_1 }; 

var list = query.ToList(); 
+0

Не знаете, как это сделать, чтобы скомпилировать ... 3 ошибки компиляции. 2x: Ожидаемое контекстное ключевое слово 'equals'. 1x: ожидаемая точка с запятой – Hoppe

+0

@ Хоппе Я не компилировал в то время, я исправил указанные ошибки – RMalke

1

попытаться дать этот выстрел:

var isDbTableQuery = dbContext.FirmFeatures.Where(f => f.FeatureId == featureId && f.IsDbTable); 
var parameters = dbContext.FirmParameters.Where(p => isDbTableQuery.Any() ? p.FeatureId == null : p.FeatureId == featureId); 
var list = parameters.ToList(); 
+0

Это выглядит многообещающим, но как мне получить фирму? То есть Ниже приведено значение null: var list = parameters.ToList(); var feature = list [0] .FirmFeature; – Hoppe

+0

был фирмой, которую вы отметили как IsDbTable? если нет, я думаю, что все результаты будут иметь FirmFeature = null; вы должны иметь возможность регистрировать SQL, который был создан, и поиграть с ним в sql-менеджере, чтобы посмотреть, что происходит. – John

+0

Это все еще делает второй вызов Db, чтобы получить эту функцию. Include, похоже, не работает ... Мне повезло? @John – Hoppe

0

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

var q = from f in dbContext.FirmFeatures 
     where f.FeatureId == featureId 
     join p in dbContext.FirmParameters on 
      (f.IsDbTable ? null : f.FeatureId) equals p.FeatureId 
     select new { p, f }; 

Или просто:

var q2 = from p in dbContext.FirmParameters.Include(p => p.FirmFeature) 
     where (p.FirmFeature.FeatureId == featureId && p.FirmFeature.IsDbTable) 
      || p.Feature == null 
     select p; 

где вы используете Include, чтобы получить FirmParameters имеющие свои FirmFeature ссылки загружены (если есть Любые).

+0

Это только выбирает параметры, но не выбирает функции – Hoppe

+0

См. Редактирование. –

0
var list = dbContext.FirmParameters 
    .Where(p => (p.FirmFeature.FeatureId == featureId && p.FirmFeature.IsDbTable) ? 
      p.FeatureId == null : p.FeatureId == featureId) 
    .ToList(); 

UPDATE

var list = dbContext.FirmParameters 
      .Join(dbContext.FirmFeature, p.FeatureId, f.FeatureId, (p, f) => new { Parameter = p, Feature = f}) 
      .Where(@f => @f.Feature.FeatureId == featureId) 
      .Where(@p => (@p.Feature.IsDbTable ? @p.Parameter.FeatureId == null : @p.Parameter.FeatureId == featureId)) 
      .Select(@x => new { Feature = @x.Feature, Parameter = @x.Parameter }) 
      .DefaultIfEmpty() 
      .ToList(); 
+0

Это не извлекает данные из таблицы FirmFeatures. Итак, это второй звонок в DB – Hoppe

+0

@Hoppe, я думаю, вы пытаетесь выполнить внешнее соединение, http://stackoverflow.com/a/3413732/1998487. Я верну свой ответ на примере. – czifro

Смежные вопросы