Czy to ma jakiś sens w praktycznym programowaniu? Bo dla mnie to istnieje tu tylko sens akademicki, pomimo ze autorzy kursu twierdzą ze pokazują przykład praktycznego zastosowania w aplikacji.
No praktyczne programowanie polega na tym, że każdy programista musi co najmniej raz w tygodniu napisać bezużyteczny wrapper, i generyczne repozytorium pomaga to osiągnąć. ;)
Ale nie jest to ani pragmatyczne, ani sensowne, no chyba, że nie masz ORMa ani żadnego gotowego dostępu do miejsca przechowywania danych, to wtedy takie bazowe DAO będzie miało sens (aczkolwiek nie ma najmniejszego powodu wyzywać porządnego DAO od repozytoriów).
Jeśli miałbym tego uzywać to sądzę ze byłoby tam co najmniej kilka metod Get z różnyumi parametrami.
No, tylko wtedy nie będzie to już generyczne.
i w jakiejś implementacji tego interfejsu
Jak to w "jakiejś"? A będzie więcej niż jedna? Po co w ogóle taki interfejs?
Ten kod jest w moim odczuciu dość nienaturalny, ten Twój serwis to tak naprawdę jakiś wrapper na ORMa. Ja w miejscu, w którym mam logikę aplikacji (czyli serwisie aplikacyjnym bądź mediatorowym handlerze) użył dbContextu i zrobił, co potrzebuję.
A widziałeś żeby ktoś przepisywał obiekty z ORM na obiekty domenowe i w drugą strone? No bo jak np przepiszesz w Hibernate (NHibernate pewnie podobnie) to tracisz co najmniej połowę zalet
ORMa czyli śledzenie zmian
Ale przecież nie trzeba mapować, bo obiekty domenowe mogą być używane przez ORMa. Ale aby to było możliwe, to domena musi spełniać warunek bycia persistence ignorance, a ORM nie może mieć żadnych wymagań co do encji, które mapuje. A nie każdy ORM na to pozwala.
Problem jest wtedy, gdy obiekty z ORMa są używane jako domenowe, czyli de facto model biznesowy operuje na strukturze bazy danych.
A to główna zaletą ORM nie jest mapowanie relacji na obiekty? Bo to mapowanie obiektów domenowych na bazodanowe i odwrotnie to widzę praktycznie w każdej aplikacji.
A w ilu przypadkach wynika to z czegoś innego niż "każda warstwa operacyjna musi mieć swoją warstwę struktur danych" albo "mamy słabego ORMa"? Bo tylko te pozostałe mogą być sensowne. :)
Przecież mapujesz co chcesz i jak chcesz. Po co trzymać jeszcze osobnę libkę z jakimiś POCOsami.
Chyba że komuś płaca za LOC
Tyle, że to nie zawsze są POCO, bo np. technologia składowania wymaga, aby to nie były POCO. To jeden przypadek, dla którego oddzielenie persistence modeli ma sens.
Drugim mogą być znaczące różnice między logiką biznesową, a potrzebami składowania. Jeśli te modele różnią się znacząco, to jest sens mieć oddzielną libkę.
W tej kwestii bardzo unikałbym twierdzenia, że któreś z tych dwóch podejść jest zawsze złe, albo zawsze dobre. To jest mocno zależne od konkretnej sytuacji.
@Aleksander32: czytałem :) pokaż te encje, której wg ciebie ef core nie da rady zmapowac :) od razu uprzedzam że z prywatnymi polami, niemutowalnymi kolekcjami i value objectami nie będzie problemów. I to bez żadnych atrybutów.
Ta nadzieja w to, że Microsoft kiedyś stworzy działającego ORMa przypomina mi te kobiety z podbitymi oczami, które wybaczają, bo "łobuz kocha najbardziej".
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace EntityFrejmłork
{
public class Wreszcie
{
[Fact]
public void UmieMapowaćPola()
{
string entryTitle = Guid.NewGuid().ToString();
using (var context = new AppDbContext())
{
var entry = new Entry { Title = entryTitle };
context.Entries.Add(entry);
entry.AddTag("Microsoft");
entry.AddTag("nie");
entry.AddTag("umie");
context.SaveChanges();
}
using (var context = new AppDbContext())
{
var entry = context.Entries.Single(x => x.Title == entryTitle);
entry.AddTag("w");
entry.AddTag("Ormy");
context.Invoking(c => c.SaveChanges()).Should().Throw<InvalidOperationException>();
}
}
[Fact]
public void RadziSobieZOdłączonymObiektem()
{
Info detached;
using (var context = new AppDbContext())
{
detached = context.Infos.Find(2);
}
using (var context = new AppDbContext())
{
var entry = context.Entries.Find(3);
entry.Info = detached;
context.Invoking(c => c.SaveChanges()).Should().NotThrow();
}
}
}
public class AppDbContext : DbContext
{
public DbSet<Entry> Entries { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<Info> Infos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=EfSsie;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
public class Entry
{
private readonly ICollection<Tag> _tags = new List<Tag>();
public virtual IReadOnlyList<Tag> Tags => _tags.ToList();
public virtual Info Info { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public void AddTag(string name)
{
if (_tags.Count > 3) // Ważna logika biznesowa
throw new InvalidOperationException();
_tags.Add(new Tag { Name = name, Entry = this }); ;
}
}
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public Entry Entry { get; set; }
}
public class Info
{
public int Id { get; set; }
public string Content { get; set; }
public Entry Entry { get; set; }
public int EntryId { get; set; } // w TVP mówili, że już niepotrzebne
}
}