Identyfikacja zasobu w Web API. Problem z projektowaniem endpointów.

0

Witam,

Tworzę proste API w .NET 5 gdzie używam używam ORM'a EF Core i dostawcę bazy danych SQL Server. Natknąłem się na problem z identyfikacją zasobów, a mianowicie gdy tworzę jakiś zasób np. Produkt to SQL Server tworzy klucz główny po swojej stronie. Nawet jeśli generuję Guid w aplikacji to jest on inny niż ten zapisany w bazie ze względu na ustawienia SQL Servera. Chciałbym po utworzeniu zasobu zwrócić w odpowiedzi utworzony obiekt wraz z identyfikatorem. Mam w związku z tym kilka pytań:

  1. Czy powinienem w ogóle zwracać obiekt po utworzeniu - czy to jest dobra praktyka?
  2. Czy powinienem posługiwać się id z bazy danych do identyfikacji zasobów? - Jeśli nie to jak identyfikować zasób?
  3. Istnieje możliwość włączenia jawnego podawania identyfikatorów podczas trwania transakcji. Czy jest to dobra praktyka? Jeśli tak to czy nie lepiej jest użyć tej funkcji na poziomie całej bazy, a nie tylko przy dodawaniu nowej instancji encji?
1

Czyżby brak wpisów wskazywał że nie ma jednoznacznych odpowiedzi na te pytania? Może by przenieść ten temat do innego działu, bo w sumie nie dotyczy tylko. NET?

1

Według mnie:

  1. Ja bym zwracał, nie trzeba by odpytywać api po nowe dane
  2. tak robię
  3. Ja bym chyba tak nie robił.
3

Używasz EF Core code-first ze wszystkimi jego "dobrodziejstwami"? Jeśli tak to jeśli dobrze pamiętam ID powinny być generowane za Ciebie i zgadzać się po stronie bazy. Jesteś pewny że czegoś nie poprzestawiałeś?

Jeśli chodzi o pytanie #1 to można tak robić, albo po prostu zwracać ID nowo utworzonego zasobu. Wszystko zależy od tego czy go w ogóle potrzebujesz, czy robisz jakieś przekierowanie po tym itp.

1

@Aventus:

Używasz EF Core code-first ze wszystkimi jego "dobrodziejstwami"? Jeśli tak to jeśli dobrze pamiętam ID powinny być generowane za Ciebie i zgadzać się po stronie bazy.

Wydaje mi się że to nie jest żaden super ficzur EFa, a po prostu

INSERT INTO table (name)
OUTPUT Inserted.ID <--- 
VALUES ('bob');

czy nie? aż chyba to sprawdzę jak to robi EF

2

@WeiXiao: chodziło mi po prostu czy się używa domyślnie tego co dostarcza EF Core- a więc między innymi że jeśli masz obiekt bez ID i zapisujesz go w bazie, to EF zajmie się tym że przypisać zwrócony ID do obiektu.

0

Dzięki panowie za odpowiedzi :) Może na przykładzie opiszę dokładniej problem z identyfikatorem. Załóżmy że mam prostą encje dwoma atrybutami: Id, Name.

public class Encja
{
   public Guid Id {get; set;};
   public string Name {get; set;}
}

Konfiguracja:

builder
   .HasKey(e => e.Id);

builder
   .Property(e => e.Name)
   .IsRequired()
   .HasMaxLength(250);

następnie dla uproszczenia umieszczę wszystko w Controllerze:

        [HttpPost]
        public async Task<ActionResult<Encja>> Create([FromBody] Encja encja)
        {
            newEncja = new Encja()
            {
                Id = Guid.NewGuid(),
                Name = encja.Name
            };

            await _context.AddAsync(newEncja);
            await _context.SaveChangesAsync();

            return Created($"api/encja/{newEncja.Id}", newEncja);
        }

Problem polega na tym, że zwracając obiekt w ten sposób Guid wygenerowany przez aplikacje jest inny od tego, który zostanie zapisany w bazie danych. Dlatego zastanawiam się jak to obejść. Po stronie konfiguracji wskazałem tyko klucz, a nawet zgodnie z konwencją tego nie musiałem robić bo EF automatycznie mapuje atrybut Id na klucz główny. Więc zastanawiam się gdzie jest problem. I doszedłem do wniosku że to może być baza danych.

0

Jak została utworzona na tabela w bazie? Użyłeś do tego migracji?

0

@Aventus, Tak użyłem migracji, na podstawie powyższej konfiguracji. Dodam że znalazłem wpis w dokumentacji, który mówi że domyślnie SQL Server nie pozwala jawnie podać wartości dla kolumny IDENTITY. Stąd moje 3 pytanie.

1

Faktycznie, już trochę czasu minęło od kiedy robiłem coś z EF czy też SQL ogólnie...

Zobacz ten artykuł, powinien pomóc: https://www.entityframeworktutorial.net/faq/how-to-set-explicit-value-to-id-property-in-ef-core.aspx

Jeśli pobawisz się z opcją IDENTITY_INSERT to na pewno da się to jakoś domyślnie ustawić.

0

Jeśli nie ma innego rozwiązania to pewnie muszę tak zrobić, chociaż wolałbym to ustawić globalnie na poziomie bazy danych :)
Dzięki Panowie !!!

1

modelBuilder.entity<T>().Propety(x=>x.guid).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
i wtedy jak masz np. w ctorze swojego obiektu i dasz mu tam


ctor()
{
Guid =Guid.NewGuid()
}

to o ile go mapujesz to zostanie zapisany Twój guid z apki (bo w bazie sie nie wygeneruje sam)

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