Присоединение к таблицам Entity Framework с использованием Linq, когда идентификаторы не существуют в обеих таблицах - PullRequest
0 голосов
/ 16 октября 2018

Ниже приведен класс, который я использовал для создания таблицы в моей базе данных с использованием Entity Framework.Я хотел бы иметь возможность связать эту таблицу с другой таблицей, Property.Однако, как мой код настроен, в таблице Instruction нет столбца Id, в классе есть свойство Property, которое затем генерирует столбец PropertyId в фактической базе данных, но свойство Property не являетсяЯ не могу использовать Linq для присоединения к этим таблицам.

Таблица инструкций

[Table("Instruction")]
public class Instruction
    {
        [Key]
        public int Id { get; set; }
        public InstructionTypes InstructionType { get; set; }
        public Property Property { get; set; } //Generates the EF property FK, but is not an ID so therefore cannot be used in linq.
    }

Таблица свойств

[Table("Property")]
    public partial class Property
    {
        [Key]
        public int Id { get; set; }
        public Address Correspondence { get; set; }
    }

Запрос на присоединение

var instruction = 
                from instructions in _context.Instructions
                join properties in _context.Properties on instructions.Property equals properties.Id
                where ...

Приведенный выше запрос выдает ошибку компилятора: `Тип одного из выражений в предложении соединения неверен.

Эта ошибка генерируется, когда я пытаюсь использовать объект свойства для объединения сPropertyID.

Как я могу изменить этот запрос, чтобы иметь возможность объединить эти две таблицы?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

В 99% всех случаев вы не хотите использовать оператор соединения.Entity Framework автоматически генерирует для вас SQL JOINS при использовании свойств навигации.

var instruction = await _context.Instructions.Where(i => i.Property...).FirstOrDefaultAsync().ConfigureAwait(false);

Обратите внимание, что в зависимости от того, используете ли вы EF6 или EF Core или с другой конфигурацией, отложенная загрузка может быть отключена (если нетЯ настоятельно рекомендую вам отключить его, поскольку это является узким местом с большой производительностью).

Поэтому вы должны использовать метод Include для активной загрузки связанной сущности.

var instruction = await _context.Instructions.Include(i => i.Property).Where(i => i.Property...).FirstOrDefaultAsync().ConfigureAwait(false);

Нопрежде чем делать это, подумайте, действительно ли вам нужен Instruction.Если нет, ваш код может стать:

var property = await _context.Properties.Where(p => p.Instructions.Any(i => ...)).FirstOrDefaultAsync().ConfigureAwait(false);

Обратите внимание, что вы должны расширить свой класс Property, чтобы он работал, чтобы иметь обратную ссылку

public partial class Property
{
    // No need for the Key attribute, as this is convention
    public int Id { get; set; }
    public Address Correspondence { get; set; }
    public int CorrespondenceId { get; set; } // Not needed in this scenario, but good practice
    public ICollection<Instruction> Instructions { get; } = new HashSet<Instruction>();
}
0 голосов
/ 16 октября 2018

Вы, кажется, новичок в linq.Таким образом, вы все еще думаете, как будто вы все еще находитесь в мире SQL.

С linq для сущностей, использование join является исключением.SQL join генерируется EF без вывода сообщений с использованием свойств навигации.

Таким образом, ваш запрос может быть:

var instruction = 
            from instruction in _context.Instructions                
            where instruction.Porperty.Correspondence.Contains("abc");

, тогда вы можете получить доступ к

instruction.First().Property.Correspondence

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

Для проверки вы можете использовать следующий код:

//assuming that Instructions is a DbSet<Instruction>
using (var context = new MyContext() ) {
    context.Instructions.Add(
        new instruction {
            Property = new Property {
                Correspondence = new Address {}
            }
        });
}

using (var context = new MyContext() ) {
    var c = context.Instructions.First();
    console.WriteLine($"{c.Id}, {c?.Property.Id}, {c?.Property?.Correspondence.Id}");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...