11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
premetto che non c'è una soluzione ottimale per tutti gli scenari e quindi, dato che non conosco la tua applicazione, quello che scriverò di seguito potrebbe essere adatto o no al tuo caso.


Stavo pensando di creare un interfaccia al cui interno avrò i vari metodi come ad esempio add - update - delete - GetAll - FindBy etc e poi un servizio che eredita da implementa questa interfaccia per effettuare linq su T entità nel mio dbcontext.

Questi sono metodi tipici di un repository. Dato che stai usando Entity Framework, non c'è l'effettiva necessità di reimplementare questi metodi dato che te li offre già il DbContext con i suoi DbSet. Quindi, a sensazione, direi che ri-applicare una seconda volta il repository pattern per avvolgere il DbContext sia superfluo. Alcuni lo fanno lo stesso per creare uno strato di astrazione ed avere meno riferimenti possibili a Entity Framework. Per me, il valore portato da questa pratica è insufficiente a giustificarne l'esistenza nella maggior parte delle applicazioni però, ripeto, c'è chi lo fa.
In una minoranza di applicazioni, che si trovano a gestire dati da una molteplicità di fonti (es. entity framework, web service, file xml, DB2) può aver senso creare dei repository per cercare di uniformare l'interfaccia di interrogazione dei dati.

A parte questa digressione sui repository, io un servizio lo creerei per accomodare le specifiche esigenze dell'applicazione che sto scrivendo. Ad esempio, se devo realizzare un'homepage con i 10 prodotti più scontati, creerò un servizio ProductService che abbia il seguente metodo:
Task<IEnumerable<ProductDto>> GetMostDiscountedProducts(int count);


Se devo aggiornare il prezzo di un prodotto, creerò questo metodo che scatenerà, come effetto collaterale, la notifica a tutti gli utenti che l'avevano inserito nella loro lista dei desideri (delegando l'invio della notifica ad altri servizi infrastrutturali, ovviamente).
Task UpdateProductPrice(int productId, ProductPriceChangeRequest request);



Poi avrò N controller in base a quello che mi serve (controller per i clienti, controller per i prodotti) dove avrò i vari HttpGet - HttpPost etc.

Sì, ok. L'importante è non mettere logica di business nei controller. Vanno nei servizi come quello che ho appena descritto. Questo per una migliore testabilità e perché fa sempre comodo tenere la logica di business in classi che potrai riutilizzare anche in altri tipi di progetto.

ciao,
Moreno

Enjoy learning and just keep making
18 messaggi dal 07 gennaio 2016
Ciao Moreno,
ora ho un altro problema che prima non stavo riscontrando.
Come già ti ho detto nelle domande precedenti sto lavorando con un database in locale.
Nel mio progetto ho quindi il mio contesto creato in automatico dal comando con le varie classi dell?object model mappate verso la propria tabella del database.

Stavo però riscontro questo errore :

InvalidOperationException: Cannot create a DbSet for 'ApplicationUser' because this type is not included in the model for the context.

la classe startup l'ho lasciata come nel tuo esempio in questo modo ora :

services.AddDbContext<WebApiDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<WebApiDBContext>();

Il mio contesto ora l'ho modificato aggiungendo la classe base IdentityDbContext<ApplicationUser> ed ora ricevo il seguente errore :

InvalidOperationException: The entity type 'IdentityUserLogin<string>' requires a primary key to be defined.


Cosa mi sfugge? Non ho mappato qualche chiave?


Grazie Moreno.


Marco.
Modificato da Pibe93 il 12 novembre 2018 22.06 -
18 messaggi dal 07 gennaio 2016
Ho rimosso i vari modelbuilder delle entità riguardanti identity che mi aveva creato il comando in automatico ed ho inserito questo base.OnModelCreating(modelBuilder); ed ora sembra funzionare.


Quello che sto facendo è corretto?


Grazie mille Moreno della pazienza.
11.886 messaggi dal 09 febbraio 2002
Contributi
Prego, figurati :)
Sì, è corretto quello che stai facendo perché invocando base.OnModelCreating(modelBuilder) hai eseguito le regole di mapping situate nella classe base IdentityDbContext<ApplicationUser>. Le sue regole di mapping riguardano tutte le entità di pertinenza alla gestione degli utenti e dei loro claim.


Ho rimosso i vari modelbuilder delle entità riguardanti identity che mi aveva creato il comando

Non so precisamente quali fossero ma non devi rimuoverli del tutto. Lasciali dopo l'invocazione a base.OnModelCreating(modelBuilder). Infatti, l'IdentityDbContext<ApplicationUser> avrà pure mappato le classi di entità che riguardano la gestione degli utenti, ma tutte le altre classi di entità che hai creato tu e che vuoi gestire con quel DbContext dovranno essere mappate.

ciao,
Moreno

Enjoy learning and just keep making
18 messaggi dal 07 gennaio 2016
Ciao Moreno,
ho rimosso soltanto le mappature riguardanti la gestione degli utenti.

Ora ho effettuato questa prova :
Ho creato un servizio dove al suo interno ho questi due metodi ,

public async Task<IEnumerable<Menu>> GetMenuAll()
{
return await _context.Menu.ToListAsync();
}

public async Task<IEnumerable<Menu>> GetMenu(string idLocale)
{
var menu = await (from m in _context.Menu
where m.Idlocale == idLocale
select m).ToListAsync();

return menu;
}


e nel controller questi due ,


[HttpGet]
public async Task<IEnumerable<Menu>> GetMenuAll()
{
return await _service.GetMenuAll();
}


[HttpGet("{idLocale}")]
public async Task<IActionResult> GetMenu([FromRoute] string idLocale)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var menu = await _service.GetMenu(idLocale);

if (menu == null || menu.Count() == 0)
{
return NotFound();
}

return Ok(menu);
}

ho un problema con la GET dove voglio farmi restituire un menu in base al campo idLocale che gli passo ma mi restituisce notfound (oppure ok ma non resistuisce niente).

Ho sbagliato qualcosa?
questa è la richiesta che eseguo --> http://localhost:80/api/Menu/{{$PROVA.PROVA}} dove PROVA.PROVA è il mio campo IDLocale della tabella Menu (nella tabella c'è un record con il campo idlocale valorizzato con PROVA.PROVA).


Grazie Mille.

Marco.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Marco,
logga la query che EFCore invia al database. Penso che guardando quella sarà subito chiaro il perché non sta restituendo risultati. Se non si capisce lo stesso, copia la query ed eseguila in Sql Server Management Studio (o altro client per il tuo database) e vedi che righe ti restituisce.

Per loggare le query inviate da Entity Framework Core, segui questo:
https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging

Non mi vorrei sbagliare ma credo che le query compaiano nell'output della console anche senza fare niente, almeno fintanto che l'applicazione gira nell'ambiente Development.

ciao,
Moreno

Enjoy learning and just keep making
18 messaggi dal 07 gennaio 2016
Ciao Moreno,
cavolo non sapevo di poter vedere la query di EFCore nell'output di VS.

Vedo che Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (9ms) [Parameters=[@__idLocale_0='?' (Size = 100)], CommandType='Text', CommandTimeout='30'] è sbagliato ovvero non passa il valore che gli voglio passare 'PROVA.PROVA' ma mi sembra di aver fatto tutto corretto.

ok forse era sbagliato come gli passo idLocale dal client.

Marco.
Modificato da Pibe93 il 13 novembre 2018 23.40 -
11.886 messaggi dal 09 febbraio 2002
Contributi

Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (9ms) [Parameters=[@__idLocale_0='?' (Size = 100)], CommandType='Text', CommandTimeout='30'] è sbagliato

No, in realtà il valore che sta passando potrebbe essere corretto. Qui EFCore sta nascondendo il vero valore del parametro per motivi di riservatezza, perché nei parametri lo sviluppatore potrebbe mettere password e numeri di carte di credito, quindi preferisce nasconderli di default.
Se vuoi vedere i reali valori dei parametri, aggiungi EnableSensistiveDataLogging() al DbContextOptionsBuilder.

Quindi, nel metodo OnConfiguring del tuo DbContext fai:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
  optionsBuilder
    .EnableSensitiveDataLogging()
    ....; //Qui altre eventuali invocazioni di metodo
}


E poi vai a riesaminare il log. Stavolta i valori dei parametri dovrebbero apparire in chiaro.

ciao,
Moreno
Modificato da BrightSoul il 14 novembre 2018 08.28 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.