Quando salvo le modifiche a DbContext, non aggiorno il mio database. Nessun errore neanche.
Sì, i dati del modulo in entrata sono compilati. Sì, la stringa di connessione è corretta, lo so perché sono in grado di recuperare i dati dal database perfettamente. Se è rilevante, è una relazione molti-a-molti.
Una roadmap è come un articolo per quanto ti riguarda che può essere associato a molti tag.
public static class RoadmapService
{
static ConkerDbEntities dbContext;
public static void createDbContext(ConkerDbEntities _dbContext)
{
dbContext = _dbContext;
}
public static void addToDatabase(Form form)
{
Roadmaps roadmap = new Roadmaps { RoadmapTitle = form.title,
RoadmapSummary = form.summary,
RoadmapBody = form.body };
var tags = new Tags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
tags[i] = new Tags();
tags[i].TagId = form.tags[i];
}
var roadmapTags = new RoadmapTags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
}
dbContext.AddRange(roadmapTags);
dbContext.SaveChangesAsync();
}
}
}
Dove viene creato dbcontext, questo è il costruttore di Startup.cs
public static SearchEngine engine;
public static ConkerDbEntities dbContext;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
dbContext = new ConkerDbEntities();
RoadmapService.createDbContext(dbContext);
engine = new SearchEngine(dbContext);
}
Non ottengo errori e non viene aggiunto nulla al database. Probabilmente sto facendo qualcosa di fondamentalmente sbagliato qui. Grazie in anticipo.
Stai utilizzando la programmazione asincrona, ma il tuo metodo non è asincrono.
usa dbContext.SaveChangesAsync();
quando si dispone di metodi asincroni, utilizzare dbContext.SaveChanges();
quando non è asincrono.
Inoltre, stai usando classi statiche, questo non dovrebbe essere il caso se stai usando l'iniezione di dipendenza. DI gestirà il ciclo di vita dei tuoi oggetti.
La tua classe non è definita come dovrebbe essere, hai alcuni errori di formato e dovrebbe assomigliare a questa:
public class RoadmapService
{
private readonly ConkerDbEntities _dbContext;
public RoadmapService(ConkerDbEntities dbContext)
{
_dbContext = dbContext;
}
public async Task AddToDatabase(Form form)
{
Roadmaps roadmap = new Roadmaps {
RoadmapTitle = form.title,
RoadmapSummary = form.summary,
RoadmapBody = form.body
};
var tags = new Tags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
tags[i] = new Tags();
tags[i].TagId = form.tags[i];
}
var roadmapTags = new RoadmapTags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
}
_dbContext.AddRange(roadmapTags);
_dbContext.SaveChangesAsync();
}
}
Quindi nel controller è possibile utilizzare il servizio così com'è
public class OrdersController : Controller
{
private readonly RoadmapService _roadmapService;
public OrdersController(RoadmapService roadmapService)
{
_roadmapService = roadmapService;
}
[HttpGet]
[Route("api/[controller]/{folio}")]
public async Task<IActionResult> Status(string folio)
{
await _roadmapService.AddToDatabase(something);
return Ok();
}
}
Vorrei anche raccomandare di studiare Linq e come è possibile evitare quei cicli foreach utilizzando select, controllare gli standard di codifica Net Core predefiniti .
Sono curioso, LINQ fornirebbe vantaggi in termini di prestazioni in questo caso rispetto a un normale ciclo continuo?
Riguarda maggiormente la leggibilità e la manutenibilità del tuo codice, nella risposta ho già inserito un link a un post in cui è meglio spiegato, stai creando debito tecnico nel tuo codice, stai inizializzando array e riempiendoli, gestendo indici e altro ancora. .., ma si riduce a questo:
Cosa c'è di più facile da leggere? Questo:
public async Task AddToDatabase(Form form)
{
Roadmaps roadmap = new Roadmaps {
RoadmapTitle = form.title,
RoadmapSummary = form.summary,
RoadmapBody = form.body
};
var tags = new Tags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
tags[i] = new Tags();
tags[i].TagId = form.tags[i];
}
var roadmapTags = new RoadmapTags[form.tags.Length];
for(int i = 0; i < tags.Length; i++)
{
roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
}
_dbContext.AddRange(roadmapTags);
_dbContext.SaveChangesAsync();
}
o questo
public async Task AddToDatabase(Form form)
{
var roadmap = new Roadmap {
RoadmapTitle = form.title,
RoadmapSummary = form.summary,
RoadmapBody = form.body
};
var roadmapTags = form.Tags
.Select(tagId => new Tag // First we take our form.tags and convert it to Tag objects
{
TagId = tagId
})
.Select(tag => new RoadmapTags // Then we take the result of the previous conversion and we
{ // transform again to RoadmapTags, we even could do this in one pass
Roadmap = roadmap, // but this way is more clear what the transformations are
Tag = tag
})
.ToList();
_dbContext.AddRange(roadmapTags);
await _dbContext.SaveChangesAsync();
}
Se hai appena iniziato a studiare la programmazione, potresti ignorarlo fino a quando non sarai più a tuo agio con le strutture for
, foreach
, while
e altre strutture di controllo . Questa è la programmazione della struttura ed è un argomento a sé stante.
Inoltre, come potrei passare l'oggetto roadmapService al costruttore del controller, non l'ho mai visto.
Questa è la magia dell'iniezione di dipendenza, lascia che il sistema crei l'oggetto per te, devi solo chiedere il tipo.
Anche questo è un argomento importante, dovresti controllare il mio link precedente alla documentazione di Microsoft, ma fondamentalmente, tutto ciò che devi fare è definire le classi come dipendenze, quindi, quando ne chiedi una, il sistema stesso controlla le dipendenze e il dipendenze di tali oggetti, fino a quando non risolve tutto l'albero delle dipendenze.
Con questo, se hai bisogno di un'altra dipendenza nella tua classe, puoi aggiungere direttamente ma non è necessario modificare tutte le classi che usano quella classe.
Per usarlo nel controller, controlla i documenti ufficiali , devi solo aggiungere dipendenze al costruttore e vincere !, in pratica due parti:
Aggiungi in Startup.class
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<MySpecialClassWithDependencies>();
...
}
Quindi nel controller:
public class HomeController : Controller
{
private readonly MySpecialClassWithDependencies _mySpecialClassWithDependencies;
public HomeController(MySpecialClassWithDependencies mySpecialClassWithDependencies)
{
_mySpecialClassWithDependencies = mySpecialClassWithDependencies;
}
public IActionResult Index()
{
// Now i can use my object here, the framework already initialized for me!
return View();
}