Ошибка The property is not a navigation property of entity type

122
14 августа 2019, 16:10

Пытаюсь установить связь, с таблицей другой в asp net core, у меня выдает ошибку:

The property 'Name' is not a navigation property of entity type 'Product'. The 'Include(string)' method can only be used with a '.' separated list of navigation property names.

Мой код:

Модель ProductDetail

[ForeignKey("Product")]
public int? ProductId { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
public int? CategoryId { get; set; }
public virtual Category Category { get; set; }
public int Count { get; set; }

Модель Product

public class Product
{
    [Required] public string Name { get; set; }
    public virtual IEnumerable<ProductDetail> ProductDetail { get; set; }
}

Контроллер:

var blog2 = _context.ProductDetails
                    .Include(b => b.Product)
                    .ThenInclude(b => b.Name)
                    .FirstOrDefault();

Всякими способами пробывал установить связь - не работает.
Гугл перерыл - не работают там решение. Заранее спасибо за помощь.

Answer 1

Когда вы делаете Include - то указываете навигационные свойства. В данном примере вы делаете выборку из таблицы ProductDetails и .Product — это навигационное свойство (оно указывает на другую таблицу).

После того, как вы подключили таблицу продуктов вы можете через .ThenInclude указывать навигационные свойства из таблицы продуктов. Допустим, в сущности продукт указано навигационное свойство "бренд продукта":

Model Product

[ForeignKey("Brand")]
public int BrandId { get; set; }
[ForeignKey("BrandId")]
public virtual Brand Brand { get; set; }

В таком случае вы могли бы в своём запросе указать это навигационное свойство бренд:

var blog2 = _context.ProductDetails
                    .Include(pd => pd.Product)
                    .ThenInclude(p => p.Brand)
                    .FirstOrDefault();

Однако Name - это не навигационное свойство продукта, это вероятнее всего просто строка:

Model Product

public string Name { get; set; }

И нужно понимать, что когда вы указываете в .Include или .ThenInclude навигационные свойства — вы подключаете сразу всю таблицу базы (сущность в терминах EF) целиком. Поэтому вам нет необходимости указывать поле Name - у вас и Name и все остальные поля таблицы продуктов подключились. (А в моём примере — вам доступны все поля таблиц ProductDetails, Products и Brands)

Поэтому эту строчку вам нужно просто исключить, она не нужна. Через Include подключаются только модели и при подключении модели сразу все её поля доступны в запросе.

После того, как вы передадите в представление вашу модель:

var model = _context.ProductDetails .Include(b => b.Product) .FirstOrDefault();

Вы сможете использовать не только поля ProductDetail, но и Product:

<table>
    @foreach(var pd in Model)
    {
        <tr>
            <td>@pd.Id</td>
            <td>@pd.Title</td>
            <td>@pd.Count</td>
            <td>@pd.Product.Name</td>
        </tr>
    }
</table>

PS Для получения продукта можно идти напрямую и не подключать никакие дополнительные таблицы:

var product = _context.Products.FirstOrDefault(p => p.Id == 12345);
if(product == null)
    throw new Exception();
var productName = product.Name;
READ ALSO
Как удалить данные из DataSet?

Как удалить данные из DataSet?

Хочу удалить из базы выделенный элемент

99
StreamWriter не хочет записывать в файл ответ [закрыт]

StreamWriter не хочет записывать в файл ответ [закрыт]

Программа считывает 2 числа с файла и выполняет матдействия, а StreamWriter не хочет записывать в файл ответ

120
Не работает IntelliSense для C# в VScode под GNU\Linux

Не работает IntelliSense для C# в VScode под GNU\Linux

Расширение установлено, проект создан через dotnet 22

123
Скопировать файл в несколько потоков в .net 3.5

Скопировать файл в несколько потоков в .net 3.5

Возможно ли скопировать файл в несколько потоков? Если да, то как? Я пытаюсь сделать что-то подобное, но оно ожидаемо не работает:

126