0

I am new to ASP.NET programming and for sure I didn't understood clearly how DbSet works in ASP. I tried to search for related questions, but I couldn't find something similar.

I have a database with the tables: Clients and Products.

In the Client table I have a DateTime entry for the expiration of the contract between "me" (the user that uses the software and the Client)

In the Products table I have a DateTime entry for when the product was sold. On this entry I have a Data validation written by me where with the code of the Client I go and retrieve a single row with the SingleOrDefault method.

If the user wants to add a Product with a selling date greater than the expiration of the contract it won't let him.

The problem is: If I (or the user) update the entry for the expiration of the contract with the Client, and then go and want to add a Product with a selling date greater than the old expiration date, but smaller than the new expiration date the Client that I get from the database in debug, in the Validation method has the old Expiration Date and all the old values for that matter.

The Client is definitely being updated since after I update it I look at him in the display Client View and it has the new data.

I have the following hierarchy in the project:

A. A controller for adding and updating the Clients where I have the following code:

// connection to the database
private ApplicationDbContext _context;

// initialize the connection to the database
public GestiuneaDeseurilorController()
{
    _context = new ApplicationDbContext();
}

// overrride the Dispose destructor
protected override void Dispose(bool disposing)
{
    _context.Dispose();
}

the method that creates and updates the Client is:

public ActionResult CreateClient(clientViewModel clientViewModel)
{
    DatabaseConnection databaseConnection = new DatabaseConnection();

    if (!ModelState.IsValid)
    {
        clientViewModel = new clientViewModel
        {
            Agency = _context.Agency.ToList(),
            DateFirma = databaseConnection.assignCompanyData(),
            Client = clientViewModel.Client
        };

        return View("AdddClient", clientViewModel);
    }
    if (clientViewModel.Client.ID == 0)
        _context.Client.Add(clientViewModel.Client);

    else
    {
        Client clientInDb = _context.Client.Single(c => c.ID == clientViewModel.Client.ID);

        clientInDb.Name = clientViewModel.Client.Name;
        clientInDb.Code = clientViewModel.Client.Code;
        clientInDb.Code = clientViewModel.Client.Address;
        clientInDb.ContractNumber = clientViewModel.Client.ContractNumber;
        clientInDb.ExpiryDate = clientViewModel.Client.ExpiryDate;
        clientInDb.Agency = clientViewModel.Client.Agency
    }

    _context.SaveChanges();

    return RedirectToAction("Client", "Clients");
}

The databaseConnection.assignCompanyData() method is a call t retrieve some that from a table. I make this call a lot in the application.

B. a Folder "Validations" in the root folder where I store my validation

the code of the validation that is causing the problem is:

class ValidateSellingDate : ValidationAttribute
{
    private ApplicationDbContext _data;

    public ValidateSellingDate()
    {
        _data = new ApplicationDbContext();
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Product product = (Product)validationContext.ObjectInstance;

        if (value == null) return new ValidationResult("Field can't be empty!");
        if (product.ClientName == null) return new ValidationResult("Field can't be empty!");

        Client client;

        try
        {
            long clientId = long.Parse(client.ClientName);

            client = _data.Client.SingleOrDefault(c => c.ID == clientId);
        }
        catch
        {
            string code = client.Code;

            client = _data.Client.SingleOrDefault(c => c.Code == code);
        }

        if (client.SellingDate > client.ExpiryDate) return new ValidationResult("Selling date can't be greater than expiry date of contract with the client!");
        else return ValidationResult.Success;
    }
}

Here I get the old values for the Client with that data. What am I doing wrong?

This might be a very dumb mistake, but I am new to programming web applications.

Andrei Dobrin
  • 1,164
  • 4
  • 19
  • 35
  • 2
    If this is Linq2Sql and you are probably re-using a context. See http://stackoverflow.com/questions/8994388/linq-to-sql-returning-old-data-after-an-update – sgmoore Oct 24 '16 at 17:11
  • I thought this was the problem, but I didn't knew what to search for. I didn't knew this was called Linq2Sql. Thank you very much! – Andrei Dobrin Oct 24 '16 at 17:46
  • The answer is here: http://stackoverflow.com/questions/18169970/how-do-i-refresh-dbcontext – Andrei Dobrin Oct 24 '16 at 18:12
  • @AndreiDobrin no, you need to use the same context within one http request and a fresh context for each http request. Sharing contexts across requests is not thread safe and will accumulate entities (and errors) forever. – usr Oct 25 '16 at 08:42
  • But it is not the same Http request. There are multiple Views between these two actions. I do not call two contexts at the same Http request. That is why I found it strange that it did this and gave the lengthy explanation about how the app works. The user needs to go to the Clients List View, then select a Client, then click update, then change the information and click save. Then he has to go to Products List view and click "Add Product" and when he clicks "save" the problem appears. There are 2 completely different requests. – Andrei Dobrin Oct 25 '16 at 08:49
  • The strange thing is that in debug in the CreateProduct Action the data was updated, the Client retrieved had the new data, but not in the Data Validation request. – Andrei Dobrin Oct 25 '16 at 08:54
  • Then Refresh *definitely* is not the solution. – usr Oct 25 '16 at 09:02
  • but it works...if I add this: var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList(); context.Refresh(RefreshMode.StoreWins, refreshableObjects); in the Data Validation code it works – Andrei Dobrin Oct 25 '16 at 09:45
  • 1
    `Sharing contexts across requests is not thread safe and will accumulate entities (and errors) forever.` "it works" means "it works on your machine under testing circumstances" but not in production. – usr Oct 25 '16 at 10:49
  • Ok, of course you are right and thank you for helping me, I am not trying to contradict you. I am trying to understand what I am doing wrong. If I have the logic written above in the comment, aren't those two different contexts? Because in the Validation I have a different context. – Andrei Dobrin Oct 25 '16 at 11:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126613/discussion-between-andrei-dobrin-and-usr). – Andrei Dobrin Oct 25 '16 at 11:37
  • Maybe the attribute is cached by the MVC framework? I don't know. Use the debugger to determine if the context is the same across requests. print obj.GetHashCode() or any equivalent technique. – usr Oct 25 '16 at 16:26

0 Answers0