#c# #mysql #asp.net-mvc
#c# #mysql #asp.net-mvc
Вопрос:
Друзья, в нем была таблица «person», в которую записывалась информация пользователя. Теперь я создал таблицу «address» для хранения адресной информации пользователя.
Теперь мне нужно реорганизовать свой код, потому что у меня проблемы с отношениями. Это мои файлы:
Person.cs
using LojaVirtual.Libraries.Lang;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace LojaVirtual.Models
{
public class person
{
/* PK */
[Key]
public int cod_person { get; set; }
public string name { get; set; }
public DateTime date { get; set; }
public string gender{ get; set; }
.
.
public string email { get; set; }
public string password { get; set; }
public addres addres { get; set; }
[ForeignKey("cod_person")]
public virtual ICollection<order> Order { get; set; }
}
}
Address.cs
using System;
using System.Collections.Generic;
using LojaVirtual.Libraries.Lang;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LojaVirtual.Models
{
public class address
{
[Key]
public int cod_address{ get; set; }
public string { get; set; }
public string neighborhood{ get; set; }
public string city { get; set; }
public string state{ get; set; }
.
.
[ForeignKey("person")]
public int? cod_person { get; set; }
public person person { get; set; }
}
}
LojaVirtualContext.cs
using LojaVirtual.Models;
using LojaVirtual.Models.ProdutoAgregador;
using Pomelo.EntityFrameworkCore.MySql;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace LojaVirtual.Database
{
public class LojaVirtualContext : DbContext
{
/*
* EF Core - ORM
* ORM -> Bibliteca mapear Objetos para Banco de Dados Relacionais
*/
public LojaVirtualContext(DbContextOptions<LojaVirtualContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<person>()
.HasOne<address>(s => s.address)
.WithOne(ad => ad.person)
.HasForeignKey<address>(ad => ad.cod_person);
}
public DbSet<person> person { get; set; }
public DbSet<order> order{ get; set; }
public DbSet<address> addres { get; set; }
}
}
Здесь, в этой строке, я получаю ошибку, которую я не могу решить:
public List<order> ObterTodosPedidosPorSituacao(string status)
{
return _banco.order
.Include(a => a.order_situation)
.Include(a => a.person)
.ThenInclude(p => p.address)
.Where(a => a.Situation == status).ToList();}
Мне нужно получить доступ к полям таблицы адресов через таблицу person. Я считаю, что это все, но я получаю сообщение об ошибке:
MySQL.Data.MySqlClient.Исключение MySqlException: ‘Неизвестный столбец ‘a.addresscod_address’ в ‘списке полей»
Я также пробовал: a.person.address, но возникает та же ошибка.
Я признателен, если кто-нибудь сможет проанализировать.
Комментарии:
1. Что такое _banco? Не могли бы вы, пожалуйста, включить полный код, включая конструктор?
Ответ №1:
Здесь у вас неправильная настройка отношений
modelBuilder.Entity<person>()
.HasOne<address>(s => s.address)
.WithOne(ad => ad.person)
.HasForeignKey<person>(ad => ad.cod_person); // <-- problem: ad is person
Тип ad
в последней строке — это тип аргумента HasForeignKey
универсального типа. Вы должны прочитать это так — аргумент универсального типа HasForeignKey
— это тип объекта, содержащий внешний ключ.
Итак, что вы здесь делаете, это, по сути, настройка PK person
объекта, который будет использоваться также как FK для address
, что делает недействительным предполагаемый FK в address
(поскольку свободная конфигурация имеет более высокий приоритет / переопределяет соглашения и аннотации данных).
С учетом сказанного, просто сопоставьте address
зависимый объект as отношения «один к одному» (объект с FK), изменив аргумент универсального типа:
.HasForeignKey<address>(ad => ad.cod_person);
Также рассмотрите возможность удаления (и вообще избегания) ForeignKey
атрибутов. Они имеют разную семантику в зависимости от применяемого места (в свойстве навигации указывается имя связанного свойства FK, а в свойстве FK указывается имя связанного свойства навигации) и могут быть легко перепутаны, как в вашем случае:
[ForeignKey("cod_person")] // <-- wrong, points to self
public int? cod_person { get; set; }
public person person { get; set; }
Это должно быть либо
[ForeignKey("person")] // the name of the below navigation property
public int? cod_person { get; set; }
public person person { get; set; }
или
public int? cod_person { get; set; }
[ForeignKey("cod_person")] // the name of the above FK property
public person person { get; set; }
но, как я уже говорил ранее, лучше избегать использования этого атрибута и настраивать отношения с fluent API, где это необходимо.
Комментарии:
1. Спасибо за отзыв. Я обновил код, получил следующее: MySQL.Data.MySqlClient. Исключение MySqlException: ‘Неизвестный столбец ‘a.addresscod_address’ в ‘списке полей»
2. Теперь я получаю этот результат: ‘Свойство или навигация ‘person’ не могут быть добавлены к типу объекта ‘address’, потому что свойство или навигация с тем же именем уже существуют для типа объекта ‘address
Ответ №2:
Это должно сработать:
public List<order> ObterTodosPedidosPorSituacao(string status)
{
return _banco.order
.Include(a => a.order_situation)
.Include(a => a.person)
.ThenInclude(p => p.address)
.Where(a => a.Situation == status).ToList();
}
Но я только предполагаю, потому что включен не весь код. Если бы я мог что-то предложить — в c # существует строгое соглашение об именах. Это не имеет большого значения, но помогает работать в командах :).
редактировать: я видел другую проблему с аннотацией данных. [ForeignKey("cod_person")]
-это избыточно. Не забудьте выполнить миграцию БД после внесения изменений.
Комментарии:
1. Спасибо за отзыв. Я обновил код, получил следующее: MySQL.Data.MySqlClient. Исключение MySqlException: ‘Неизвестный столбец ‘a.addresscod_address’ в ‘списке полей»
2. Теперь я получаю этот результат: ‘Свойство или навигация ‘person’ не могут быть добавлены к объекту типа ‘address’, потому что свойство или навигация с тем же именем уже существуют для объекта типа ‘address’. ‘