Entity Framework, relacyjna baza danych i dowanie rekordu

0

Cześć
ostatnio miałem problem z pobieraniem danych (dziękuję za pomoc przy ogarnięciu tematu),
a teraz nie radzę sobie z dodawaniem nowego rekordu do tabeli korzystając z Entity Framework.

Struktura tabelek wygląda tak:

    public class User
    {
        [Key]
        [Column(TypeName = "uniqueidentifier")]
        [Required]
        public Guid UserID { get; set; }

        [Column(TypeName = "nvarchar(100)")]
        [Required]
        public string UserName { get; set; }

        public ICollection<Ticket> Tickets { get; set; }
        public ICollection<Message> Messages { get; set; }
    }

    public class Message
    {
        [Key]
        [Column(TypeName = "uniqueidentifier")]
        [Required]
        public Guid MessageID { get; set; }

        [Required]
        public Guid TicketID { get; set; }

        [Column(TypeName = "uniqueidentifier")]
        [Required]
        public Guid OwnerID { get; set; }

        [Column(TypeName = "nvarchar(max)")]
        [Required]
        public string Information { get; set; }
		
        public Ticket Ticket { get; set; } 
        public User User { get; set; }
    }

    public class Ticket
    {
        [Key]
        [Column(TypeName = "uniqueidentifier")]
        [Required]
        public Guid TicketID { get; set; }

        [Column(TypeName = "uniqueidentifier")]
        [Required]
        public Guid OwnerID { get; set; }

        public User User { get; set; }
        public ICollection<Message> Messages { get; set; }
    }

Korzystam z relacji między tabelami:

  • W tabeli "Ticket" mam wpisy których właściciel jest w tabeli "User".
  • Każdy wpis może mieć wiele wiadomości (tabela "Message") napisanych przez różne osoby, które również są w tabeli "User".

Z wyciąganiem danych nie mam już problemu, ale teraz chciałbym dodać nowy rekord do tabeli "Message". Próbowałem to zrobić w taki sposób:

_dbContext.Messages.Add(message);
await _dbContext.SaveChangesAsync();

Niestety mam błąd:

Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
 ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'UserID'.

Pomyślałem, że w takim razie spróbuję zrobić to idąc przez tabelę "User". Kombinowałem coś w rodzaju:

_dbContext.Users.Where(p => p.UserID == userID).Include(p => p.Messages).FirstOrDefault().Messages.Add(message);
await _dbContext.SaveChangesAsync();

Jednak tym razem mam błąd:

Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'UserID'.
Invalid column name 'UserID'.

Bedę wdzięczny za wskazówki jak to rozwiązać i prawidłowo dodać rekord do tabeli "Message".

Dzięki i pozdrawiam :)

0

A w bazie istnieje kolumna UserId w tej tabelce?

0

W tabeli "Message" jest kolumna "OwnerID", a w tabeli "User" kolumna "UserID". Klucz obcy ustawiłem w taki sposób:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Message>()
        .HasOne(p => p.User)
        .WithMany(b => b.Messages)
        .HasForeignKey(s => s.OwnerID)
        .OnDelete(DeleteBehavior.ClientCascade);
}

I przy pobieraniu danych jak i przy dodawaniu nowego ticketu (nowe rekordy pojawiają się wtedy zarówno w tabeli "Ticket" jak i "Message") wszystko działa. Tylko przy dodawaniu osobno rekordu do tabeli "Message" jest problem. Ujednoliciłem jednak nazwy wszystkich kolumn na "UserID" i działa...
Czyli źle ustawiłem klucz obcy? Czy może jednak nazwy kolumn muszą być zawsze identyczne?

0

Ogólnie EF Core standardowo przy migracjach stosuje sie do następującego nazewnictwa:
Przy modelach:

public class User
{
     public Guid Id { get; set; }
}
public class Book
{
     public Guid Id { get; set; }
     public Guid? UserId { get; set; }
     public virtual User User { get; set; }
}

Nazwy tabel w dbContext:
Users
Books

Jak przyjmiesz taką zasadę nazewnictwa to przy tworzeniu migracji klucze obce ustawią się same. Dodawanie atrybutów [Key] itp. też będzie niepotrzebne, chyba że Twoim kluczem będzie właściwość o innej nazwie niż "Id".

1
filipek686 napisał(a):

I przy pobieraniu danych jak i przy dodawaniu nowego ticketu (nowe rekordy pojawiają się wtedy zarówno w tabeli "Ticket" jak i "Message") wszystko działa. Tylko przy dodawaniu osobno rekordu do tabeli "Message" jest problem. Ujednoliciłem jednak nazwy wszystkich kolumn na "UserID" i działa...
Czyli źle ustawiłem klucz obcy? Czy może jednak nazwy kolumn muszą być zawsze identyczne?

A na czym ten problem polega? Przypisujesz OwnerId przy dodawaniu Message?
Pokaż jak dodajesz Message.

Generalnie dobrze się trzymać konwencji ale po te jest mapowanie FluentAPI, żeby to jawnie, jednoznacznie zdefiniować.
Jeśli używasz FluentApi w OnModelCreating to nie używaj anotacji.

Np. ta anotacja w Message może być problemem bo tu OwnerId nie będzie unique.

[Column(TypeName = "uniqueidentifier")]
[Required]
public Guid OwnerID { get; set; }

1 użytkowników online, w tym zalogowanych: 0, gości: 1