Вкратце, как Entity Framework должна работать со связанными таблицами.
aspnetcore 2.0
public class Table1{
[Key]
public int Id{get;set;}
[ForeignKey("Table2")]
public int Table2Id {get;set;}
public virtual Table2 Table2{get;set;}
}
public class Table2{
[Key]
public int Id{get;set;}
}
Я предположил, что с заявлением
var t1 = context.Table1List.FirstOrDefault( j => j.Id == 1)
автоматически заполнил бы Table2, но t1.Table2 имеет значение null.
Если бы я должен был вызвать context.Table2List.FirstOrDe ..... тогда t1.Table2 заполняется даже без установки свойства. Таким образом, EF распознает, что связь просто не заполняется, пока я физически не позвоню в БД.
Я понимаю, как EF должен работать неправильно, или это просто ошибка в моем коде. Может что-то связано с ленивой загрузкой.
Я читал, читал и читал руководства Microsofts, но не очень понимал, как это должно работать по сравнению с тем, как это работает на самом деле.
Таблицы 1 и 2 связаны друг с другом только один к одному.
Вам нужно добавить включение в заполненную таблицу 2: context.Table1List.Include(t => t.Table2).FirstOrDefault( j => j.Id == 1)
Пожалуйста, проверьте мой ответ.
@aguafrommars Совершенно верно. такой же, как мой ответ.





Оставляя разводку в основном на усмотрение и предполагая отношение «1 ко многим», вы хотели создать набор моделей, которые выглядят так?
public class Table1
{
public int Id { get; set; } // Primary key by convention
[ForeignKey("Table2")]
public int Table2Id { get; set; }
public Table2 Table2 { get; set; }
}
public class Table2
{
public int Id { get; set; } //Primary key by convention
public ICollection<Table1> Table1s { get; set; }
}
см. комментарий к AmirReza-Farahlagha
Обновлять:
Вы должны изменить свою модель, например:
public class Table1{
public int Id{get; set;} //Primary key by convention
[ForeignKey("Table2")]
public int Table2Id{get; set;}
public virtual Table2 Table2{get; set;}
}
public class Table2{
public int Id{get; set;} //Primary key by convention
public virtual Table1 Table1{get; set;}
}
И в вашем контексте вы должны установить это:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure table1 & table2 entity
modelBuilder.Entity<Table2>()
.HasOptional(s => s.Table1) // Mark Table1 property optional in Table2 entity
.WithRequired(ad => ad.Table2); // mark Table1 property as required in Table2 entity. Cannot save Table1 without Table
}
И когда вы хотите получить данные из одной таблицы, а также получить данные из связанной таблицы, вы используете метод Include в своем запросе, например:
var result = var t1 = context.Table1List.Include(x=>x.Table2).FirstOrDefault( j => j.Id == 1);
с этим кодом у вас есть данные о связанной таблице.
Если хотите, я могу создать для вас больше образцов.
Вы только что скопировали / вставили определения классов из ответа @spender? Большой LOL
Не повезло. У меня уже есть много моделей, настроенных таким образом. они тоже не работают. Однако я считаю, что вы соглашаетесь с предположением, что EF должен заполнять их автоматически. Также таблицы 1 и 2 имеют отношение 1 к 1. Таким образом, список table1s не является верным утверждением. Я считаю, что моя модель показывает это. Также в таблицах 1 и 2 используются идентификаторы. Если бы я запустил ваш код, он не нашел бы Table2Id.
@Mike Вы выбрали виртуальную собственность?
Я удалил последний комментарий ... добавление Include сработало. Это все, что я сделал. Однако у меня сложилось впечатление, что мне не придется этого делать. и добавление include по сути то же самое, что я пишу еще один оператор для выборки таблицы. Не думаю, что пробовал использовать параметр WithRequired в OnModelCreating. это выглядит положительно. Я тоже попробую. Однако ваш пример все еще неверен. Столбца с именем Table2Id нет. Просто Table1 и 2 имеют один и тот же идентификатор. Если бы мне пришлось добавить атрибут Column ("..."), то я получил бы повторяющуюся ошибку. Мой пример не показывает виртуальный, но мой код показывает.
@Mike На мой взгляд, ваша проблема в вашей таблице, потому что она неверна, пожалуйста, проверьте эту строку entityframeworktutorial.net/code-first/…, чтобы узнать информацию о создании таблицы.
Я не думаю, что ошибка связана с моим кодом или, по крайней мере, с моими моделями и БД, потому что добавление Include (func) работало без ошибок. Итак, это говорит мне, что это параметр, который установлен неправильно. Я отметил наш ответ, потому что он сработал. Просто не так, как я хотел.
@ Майк, я правда не понимаю, ты тестируешь метод Include ?? Если да, то какой у вас результат? У вас есть ошибки ?? Я думаю, вы получаете firstordefault, и прежде всего данные, нет данных о table2
как упоминалось в двух комментариях выше. Да, я протестировал включение, и это сработало. Вот почему я поставил вам оценку.
То, что вам нужно, называется Ленивая загрузка
Проверив документацию, вы увидите, что вы должны явно включить отложенную загрузку:
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
И ваше свойство Table2 должно быть virtual:
public class Table1
{
public virtual Table2 Table2{get;set;}
}
Вам даже не нужен внешний ключ Id!
Я попробую отложить загрузку ... Думаю, я пробовал это раньше, но не помню, почему id не работал. Пример, который у меня был, немного отличался от вашего. Вернемся к вам по этому поводу. Атрибут внешнего ключа понадобится вам, если у вас нет точного формата для свойств или если вы не установили его в onModelBuilding. Ваше последнее утверждение не совсем верно.
@ Майк, конечно, проверьте также эта документация. И, как я вижу, вы используете оба Key. ForeignKey, вам следует ввести новое свойство для вашего внешнего ключа.
Нет опции для UseLazyLoadingProxies, есть ли для этого конкретная ссылка?
Обратите внимание: Эта функция была представлена в EF Core 2.1. Какая у вас версия EF Core?
2.0 AmirReza ... помогло просто добавление Include в контекст. На тот момент все работало.
@Mike Да, это еще одна возможность загрузки связанных данных, так называемая Нетерпеливая загрузка. Вам решать, какую возможность использовать, но если вам нужна отложенная загрузка, как в вашем вопросе, у вас должна быть версия EF Core 2.1.
Ваш дизайн сбивает с толку - должен ли
Idбыть первичным ключомTable1или внешним ключомTable2? Не могли бы вы определить SQL-определение обеих таблиц?