简体   繁体   中英

How To Clear Uninserted POCO's From DbContext? - Entity Framework Code First

I am currently developing a project for a university which provides students to create an account and with this account they can calculate their GPA, accessing the forum and screen sharing. I am using ASP.NET MVC and ASP.NET Web Api technologies. I developed my Business Layer and made "Manager" classes that helps to make db operations for all POCOs of my project. All of my manager classes uses same DbContext which is coming from BaseManager class. I have some set of rules in my POCO classes that prevents db insertion if the creedientals are wrong.

When I enter these fields wrong, db insertion fails as expected. But after that when I insert the correct values (entering a value to a field that should not be null etc.) db insertion fails again and same validationerrors shows up as before failed attempt despite that the mistakes are corrected.

Here is my User POCO class(I am sharing the 2 fields that I'm talking about):

    [Table("UserTable")]
    public class User
    {
      [Required]
      [Index(IsUnique = true)]
      [MaxLength(30, ErrorMessage = "Username can not exceed 30 characters!")]
      public string Username { get; set; }

      [Required]
      [Index(IsUnique = true)]
      [MaxLength(50, ErrorMessage = "Email can not exceed 50 characters!")]
      [DataType(DataType.EmailAddress)]
      [RegularExpression("^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}     \\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")]
      public string Email { get; set; }
 }

When I check the DbSet of my corresponding POCO class, I saw all of my attempted objects also kept locally just like my 2 records on the database. Here's the screenshot:

Here's my Business Layer logic:

  • I created Generic Repository classes that can be implemented by any POCO classes.
  • I created UnitOfWork class that creates DbSontext with SingletonPattern (UnitOfWork object creating at UnitOfWorkBase class) and has 2 methods used by Manager and ComplexManager classes.
    • 1.Generic GetRepository
    • 2.Generic GetManager
  • I use manager classes in order to define every POCO's set of methods like CRUD and POCO specified methods (like UserManager has CheckCreedientals for login method). All db operations made here.
  • I use complex manager classes in order to achieve methods that requires more than one manager. (Like createAccount method that takes place in AccountComplexManager class creates two POCO classes and adds them into database.). There is no db operations except commiting the changes made here. The method of corresponding manager class is being called and db operations are done by these methods of manager classes' methods.
    • 1.Student POCO
    • 2.User POCO
  • I created 3 base classes for my Managers in order to reduce dummy code.
    • 1.MotherBaseManager class: UnitOfWork object created here and using by all managers that makes db operations. This class also inherited by the next 2 classes. It has only Context method which returns the UnitOfWork object.
    • 2.BaseComplexManager class: Base class of ComplexManagers classes. Has GetManager method in order to get corresponding managers to achieve some db tasks and Save method in order to commit changes on db.
    • 3.BaseManager class: Base class of Manager classes. It has Get Repository class in order to get corresponding repository classes for performing db operations such as CRUD.

My Class View of adjusted version of Business Layer is:

I want to purge dbSet local from insert-attempted objects without restarting the application in order to give chance users to correct their mistakes and create account again.

If I have mispelled or mistaken at some point please forgive me. Any helps would be appreciated. Thanks!

Besides the very valid comment from sellotape about DbContext lifetime, there are a couple of things you can do.

If you want to make the least changes to your app, then I'd suggest to use transactions, eg

using (var transaction = dbContext.Database.BeginTransaction())
{
    try
    {
        // Prepare POCOs to be stored
        ...
        dbContext.SaveChanges();
        transaction.Commit();
    }
    catch (Exception)
    {
        // Handle failure
    }
}

If SaveChanges() fails, your transaction will be automatically rolled back and all the objects added in this block will be removed from dbContext .

You can find more info in MSDN on transactions in EF Core or EF 6 .

However, I would suggest you to rethink your validation scheme instead. Data validation is not supposed to happen on the database level - validation should happen much earlier in the request lifetime, maybe even before you create POCOs to be stored to the database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM