Search code examples
c#oracle-databaseentity-frameworkmstest

Adding list of records Failed in Entity Framework


I tried to add entities to the database with Entity Framework, but it failed. Here is the source code that is responsible for adding a list of entities to the database:

public class EfUserPermissionRepository : IUserPermissionDal
{

    private readonly EfDbContext _context;

    public EfUserPermissionRepository(EfDbContext context)
    {
        if (context == null)
            throw new ArgumentNullException(typeof(EfDbContext).ToString());

        this._context = context;
    } 

    //It adds USERPERMISSION list to database. 
    public void Add(List<USERPERMISSION> entities)
    {

        try
        {
            if (entities == null || !entities.Any())
                throw new ArgumentNullException();

            foreach (USERPERMISSION value in entities)
            {

                if (value == null)
                    continue;

                this._context.USERPERMISSION.Add(value);
            }

            this._context.SaveChanges();

        }
        catch (Exception exception)
        {
            throw exception;
        }

    }

    public USERPERMISSION Add(USERPERMISSION entity)
    {
        _context.USERPERMISSION.Add(entity);
        _context.SaveChanges();
        return entity;
    }

}

I have a class named USERPERMISSION. It has two foreign key relations with the other class named USER and PAGE. Here is the content of the USERPERMISSION class:

[Table("USERPERMISSION")]
public class USERPERMISSION
{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [ForeignKey("USER")]
    public int USERID { get; set; }
    [ForeignKey("PAGE")]
    public int PAGEID { get; set; }
    public int? ADD { get; set; }
    public int? EDIT { get; set; }
    public int? DELETE { get; set; }
    public int? READ { get; set; }
    public int? LIST { get; set; }
    public int? REPORT { get; set; }
    public int? PUBLISH { get; set; }
    public int? CONFIRM { get; set; }
    public int ACTIVE { get; set; }
    [StringLength(30)]
    public string CODE { get; set; }

    public virtual USER USER { get; set; }
    public virtual PAGE PAGE { get; set; }

}

In order to test the Add method defined in EfUserPermissionRepository, I devised a test code. I get all USERPERMISSION of user 1 and copy it to user 2. Currently, user 1 has 26 user permissions, whereas user 2 has not got any USERPERMISSION. My intention is to copy all USERPERMISSION lists of user 1 to user 2 and save them to the database. Here is the test code:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PROJECT.Tests.Soyut;
using PROJECT.Entity.Models;
using System.Collections.Generic;
using System.Linq;

namespace PROJECT.Tests
{
[TestClass]
public class UserPermissionManagerTest : TestBase
{

    private int UserId1 { get; set; }

    private USER User2 { get; set; }
    
    private List<USERPERMISSION> UserPermissionList1 { get; set; }

    /// <summary>
    /// The procedure where the <code>Add</code> procedure was tested against user 2.        
    /// 
    /// It is hoped that it will be successful.
    /// </summary>
    [TestMethod]
    public void USERPERMISSIONAdd_001()
    {

        //’UserPermissionManageri’ is a Business layer component that emerges from TestBase.
        List<USERPERMISSION> list = UserPermissionManageri.Add(UserPermissionList1);
        
        Assert.IsNotNull(list);

        Assert.AreEqual(true, list.Any());


    }

    [TestInitialize]
    public void TestClassInitialize()
    {
        UserId1 = 1;                       

        //’UserManageri’ is a Business layer component that emerges from TestBase.
        User2 = UserManageri.Get(2);

        Assert.IsNotNull(User2);
        
        //Creates a new list by getting all user permission list of user 1 to user 2.
        UserPermissionList1 = this.CopyUserPermissionList(UserId1, User2);

        Assert.IsNotNull(UserPermissionList1);

        Assert.AreEqual(true, UserPermissionList1.Any());

    }

    private List<USERPERMISSION> CopyUserPermissionList(int sourceUserId, USER targetUserToCopy)
    {

        //getting all user permission list of the sourceUserId. 
        List<USERPERMISSION> list = UserPermissionManageri.List(p => p.USERID == sourceUserId);

        //ensure that the list is not null.
        Assert.IsNotNull(list);

        //ensure that the list has a value. 
        Assert.AreEqual(true, list.Any());

        List<USERPERMISSION> copyList = new List<USERPERMISSION>();

        //copying the list to the copylist 
        foreach (USERPERMISSION value in list)
        {
            if (value == null)
                continue;

            copyList.Add(new USERPERMISSION()
            {
                USERID = value.USERID,
                PAGEID = value.PAGEID,
                ADD = value.ADD,
                EDIT = value.EDIT,
                DELETE = value.DELETE,
                READ = value.READ,
                LIST = value.LIST,
                REPORT = value.REPORT,
                PUBLISH = value.PUBLISH,
                CONFIRM = value.CONFIRM,
                ACTIVE = value.ACTIVE,
                CODE = value.CODE,
                USER = value.USER,
                PAGE = value.PAGE,
                ID = 0
            });

        }

        //assigning targetUserToCopy to all elements of copyList 
        foreach (USERPERMISSION permission in copyList)
        {
            if (permission == null)
                continue;

            permission.USER = targetUserToCopy;
            permission.USERID = targetUserToCopy.ID; 
        }

        //returning the copylist.
        return copyList;

    }

   
}
}

USERPERMISSIONAdd_001 runs successfully, that is, test function is green when I run it; however, it does not make any changes in the database. Where am I wrong? Thanks in advance.


Solution

  • As Panagiotis Kanavos pointed out, I start by isolating the problem. I discard the UserPermissionManageri in test UserPermissionManagerTest and create a new DbContext in UserPermissionManagerTest. Test class looks like this:

    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using PROJECT.Tests.Soyut;
    using PROJECT.Entity.Models;
    using System.Collections.Generic;
    using System.Linq;
    using PROJECT.Dal.Concrete.EntityFramework;
    
    namespace PROJECT.Tests.Concrete.BusinessLayer
    {
      [TestClass]
      public class UserPermissionManagerTest : TestBase
      {
    
        private int UserId1 { get; set; }
    
        private USER User2 { get; set; }
        
        private List<USERPERMISSION> UserPermissionList1 { get; set; }
        
        private static EfDbContext EfDbContexti { get; set; }
    
        /// <summary>
        /// The procedure where the <code>Add</code> procedure was tested against user 1665.        
        /// 
        /// It is hoped that it will be successful.
        /// </summary>
        [TestMethod]
        public void USERPERMISSIONAdd_001()
        {
    
            IEnumerable<USERPERMISSION> list = EfDbContexti.USERPERMISSION.AddRange(UserPermissionList1);
    
            EfDbContexti.SaveChanges();
    
            Assert.IsNotNull(list);
    
            Assert.AreEqual(true, list.Any());
    
        }
    
        [TestInitialize]
        public void TestClassInitialize()
        { 
    
            UserId1 = 17;
    
            EfDbContexti = new EfDbContext();
    
            User2 = EfDbContexti.USER.FirstOrDefault(p => p.ID == 1665);
            
            //User2 = UserManageri.Get(1665);
    
            Assert.IsNotNull(User2);
            
            //Creates a new list by getting all user permission list of user 17 to user 1665
            UserPermissionList1 = this.CopyUserPermissionList(UserId1, User2);
    
            Assert.IsNotNull(UserPermissionList1);
    
            Assert.AreEqual(true, UserPermissionList1.Any());
    
        }
        
        [ClassCleanup]
        public static void TestClassCleanup()
        {
    
            if (EfDbContexti != null)
            {
                EfDbContexti.SaveChanges();
                EfDbContexti.Dispose();
                EfDbContexti = null;
            }
        }
    
        private List<USERPERMISSION> CopyUserPermissionList(int sourceUserId, USER targetUserToCopy)
        {
    
            //getting all user permission list of the sourceUserId. 
            
            IQueryable< USERPERMISSION> iqueryable =  EfDbContexti.USERPERMISSION.Where(p => p.USERID == sourceUserId);
    
            Assert.IsNotNull(iqueryable);
    
            List<USERPERMISSION> list = iqueryable.ToList();
    
            //ensure that list is not null.
            Assert.IsNotNull(list);
    
            //ensure that list has a value. 
            Assert.AreEqual(true, list.Any());
    
            List<USERPERMISSION> copyList = new List<USERPERMISSION>();
    
            //copying the list to copylist 
            foreach (USERPERMISSION value in list)
            {
                if (value == null)
                    continue;
    
                copyList.Add(new USERPERMISSION()
                {
                    USERID = value.USERID,
                    PAGEID = value.PAGEID,
                    ADD = value.ADD,
                    EDIT = value.EDIT,
                    DELETE = value.DELETE,
                    READ = value.READ,
                    LIST = value.LIST,
                    REPORT = value.REPORT,
                    PUBLISH = value.PUBLISH,
                    CONFIRM = value.CONFIRM,
                    ACTIVE = value.ACTIVE,
                    CODE = value.CODE,
                    USER = value.USER,
                    PAGE = value.PAGE,
                    ID = 0
                });
    
            }
    
            //assigning targetUserToCopy to all elements of copyList 
            foreach (USERPERMISSION permission in copyList)
            {
                if (permission == null)
                    continue;
    
                permission.USER = targetUserToCopy;
                permission.USERID = targetUserToCopy.ID; 
            }
    
            //returning the copylist.
            return copyList;
    
        }
    
       
    }
    

    }

    Since TestBase has another independent DbContext variable, this situation causes the exception below:

    Entity object cannot be referenced by multiple instances of IEntityChangeTracker. while adding related objects to entity in Entity Framework.

    When I remove the inheritance between UserPermissionManagerTest and TestBase the problem has disappeared and relevant records are successfully saved to the database.