0

I have asp.net core web api with React client. I'm adding data through my user interface created in React. In my api, Db context is added as scoped service, and each time my request finishes and new one is started, all my data from previous request is lost. This is how my Configure services looks like:

 services.AddDbContext<TicketingContext>(o=>o.UseLazyLoadingProxies().UseSqlServer(connectionString));

Controller method for posting data looks like this:

 [HttpPost("{id}/tickets")]
    public IActionResult CreateNewTicket(string id,
        [FromBody] TicketForCreationDto ticketForCreation)
    {
        if (ticketForCreation == null)
        {
            return BadRequest();
        }

        var ticketEntity = _mapper.Map<Ticket>(ticketForCreation);
        _ticketRepository.AddNewTicket(ticketEntity);
        _ticketRepository.AddTicketToClient(id, ticketEntity);
        if (!_ticketRepository.Save())
        {
            throw new Exception("Creating ticket failed on save");
        }

        var ticketToReturn = _mapper.Map<TicketDto>(ticketEntity);



        return CreatedAtRoute("GetTicket", new {id=id, ticketId = ticketToReturn.Id }, ticketToReturn);
    }

and methods in repository like this: AddNewTicket:

  public void AddNewTicket(Ticket ticket)
    {
        if (ticket.Id == Guid.Empty)
        {
            ticket.Id = Guid.NewGuid();
        }

        var dispatcher = AssignTicketToDispatcher(ticket);
        if (dispatcher == null)
        {
            throw new Exception("There are no dispatchers matching this ticket");
        }

        dispatcher.UserTickets.Add(new UserTicket()
        {
            IdentityUser = dispatcher,
            Ticket = ticket,
            UserId = dispatcher.Id,
            TicketId = ticket.Id
        });


        _context.Tickets.Add(ticket);
    }

AddTicketToClient:

  public void AddTicketToClient(string id, Ticket ticket)
    {
        var client = _identityUserRepository.GetClient(id);
        if (client == null)
        {
            client = _context.Users.Where(u => u.UserName == "username").FirstOrDefault();
        }
        client.UserTickets.Add(new UserTicket()
        {
            IdentityUser = client,
            Ticket = ticket,
            UserId = client.Id,
            TicketId = ticket.Id
        });
    }

Save:

 public bool Save()
    {
        return (_context.SaveChanges() >= 0);
    }

I want to be able to store data gained through multiple requests. Does anyone have idea how to do that?

kika123
  • 31
  • 9
  • We need to see the code from your controller – BrianM Feb 10 '20 at 10:26
  • [Storing data between requests in dbcontext](https://stackoverflow.com/q/53956235/3110834) – Reza Aghaei Feb 10 '20 at 10:27
  • You always have the option of using session, but in general it's not good idea to use server resources to track changes in such scenarios. In scenarios like a simple shopping basket, list editing/batch editing, completing a wizard, ... you can track changes at client-side. – Reza Aghaei Feb 10 '20 at 10:29
  • I've edited post and added part of controller and repository that are in charge for adding data to db.. – kika123 Feb 10 '20 at 10:38
  • Why not use database to store / retrieve? Is the data getting lost before save? – JMP Feb 10 '20 at 10:48
  • @JP sorry, my english is not the best, so it may happen that I've used wrong expression..I want to store all of my data from multiple requests and use it later in other requests – kika123 Feb 10 '20 at 10:48
  • I jus mean could store all data from the requests, linked with a common key value. Then retrieve later as needed by the common key value. I might be missing the details though! – JMP Feb 10 '20 at 10:51
  • But when using dbcontext as scoped service it's not possible (as far as I know, but I'm still begginer, so please don't judge me if I'm saying wrong) – kika123 Feb 10 '20 at 10:51
  • Ok sorry so it is not saving to database then, which is how you want to store. – JMP Feb 10 '20 at 11:04
  • 1
    @kika123 in *all* services, the data is stored in the database, not retained in RAM between calls. That's what allows services to be deployed on multiple servers and load balanced, packaged in Docker containers etc. That goes for both Nodejs and ASP.NET. `DbContext` is meant to hold the data during a request then store *all* of it in the database. *Some* data that need to be reused can be cached - again all stacks offer a way to cache data. – Panagiotis Kanavos Feb 10 '20 at 11:49
  • @kika123 besides, when you use *React*, the place to store state *is* React, not the service. That's a fundamental concept, which is why Redux and stores exists. So the question is, why do you want to save the state on the *client* instead of the SPA? – Panagiotis Kanavos Feb 10 '20 at 11:51
  • @PanagiotisKanavos thank you for your answer and clarification of Dbcontext..The thing is that I have to enter a lot of data and I thought about entering it during few requests. (This is not any serious app for production, I'm doing this as part of a project in my college) Anyway, I want to store all of that data in my localDb , but every time I stop running application and rerun it again I loose data from previous request ..I want to point out that i have that data in my db after request but on new run of program it loses.. – kika123 Feb 10 '20 at 18:25
  • @kika123 LocalDB won't lose the data, unless you point it to the wrong database. During debugging, content files in the source project are copied to the `bin/Debug` folder, including any `mdf` files. If your LocalDb path points to the `mdb` file in `bin/Debug`, you'll end up connecting to a new empty one each time. LocalDB is only meant for development anyway. Use a proper SQL Server Express database for production instead – Panagiotis Kanavos Feb 11 '20 at 07:55

1 Answers1

1

Use the database as it's the best method you have for persisting your data.

So When you do a request - at the end of the request, after your latest data is saved - query for the data from previous requests that you need and return it.

e.g. retrieve the last 5 requests saved newest first (where id is example for your primary key field):

var latestSaved = _context.UserTickets.OrderByDescending(x => x.id).Take(5);

Or amend to return all relevant data for e.g. active user by passing a user id stored client side.

Pass through any params you need to request the relevant data. Use joins / includes set up in your entities. Whatever you need to do - make use of your entity relationships to get what you need from you database. Why try and replicate what it already does? :)

JMP
  • 1,864
  • 2
  • 8
  • 16
  • Thank you for your time and answer :) I did all of that and everything works fine during each request. But I want accomplish that with every new request I can get data from previous request/ previous requests. I've thougth that maybe adding dbcontext as singleton service inside of my configure services will make things right, but then I've read that that is bad practice so I didn't event try. Is there maybe a way to set that up inside of MyContext class? – kika123 Feb 10 '20 at 11:27
  • 2
    The problem with a singleton is that it is a singleton - not per user. Maintaining state in a backend API is terrible (among other things not all clients can send a session cookie and timeouts are bad to handle). Youre 2 storage sides are the database and the browser (i.e. there is no need to request the same data over and over). I.e. you could number tickets and only send the new ones, not all tickets - and the user client side is remembering which tickets the user still sees. No sense in wiping the data there. – TomTom Feb 10 '20 at 11:54
  • Not singleton, keep it scoped. Just query as needed. – JMP Feb 10 '20 at 12:06