0

I have an Asp.Net MVC 5 using Entity Framework 6. I am using Unity.MVC5 Version 1.2.3.0

The issue I am having is that I would get the following error on certain scenarios when saving to the database

Additional information: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

After troubleshooting the issue I believe it has to do with how I have Unity.MVC5 configured. Here is my Unity.Config.cs

public static class UnityConfig
{
    public static void RegisterComponents()
    {
         var container = new UnityContainer();      
        // register all your components with the container here
        // it is NOT necessary to register your controllers    
        // e.g. container.RegisterType<ITestService, TestService>();
         container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);

    container.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new MasterContext()));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

    }

}

So my controller would have something like this

private IService _Service;
MyController(IService service)
{
    _Service = service;
}

However it looks like the data is not refreshing, Although when I use a SQL Profiler , it shows as it is making a call but the data is not refreshed as I do a breakpoint it still has old data. If I do away with the Unity.MVC injecting the classes, then the data gets refreshed and savechanges works fine.

I am overwriting the EF Context SaveChanges , here is the code

public override int SaveChanges()
{
    var autoDetectChanges = Configuration.AutoDetectChangesEnabled;

    try
    {
        Configuration.AutoDetectChangesEnabled = false;
        ChangeTracker.DetectChanges();

        var errors = GetValidationErrors().ToList();

        if (errors.Any())
        {
            throw new DbEntityValidationException("Validation errors found during save.", errors);
        }

        //For modified column
        var changedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Modified)
            .Select(t => new
            {
                    Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
                    Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
                    objectContext = ((IObjectContextAdapter)this).ObjectContext,
                    ent = t,
            });
        foreach (var item in changedInfo)
        {
            if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
            {
                var result = GetDifference.GetChangedValues(item.Original, item.Current, item.objectContext, item.ent);
                HistoryLog history = new HistoryLog();
                history.Description = result[0];
                history.TableFields = result[1];
                history.UserId = userId;
                history.TableAction = "Modified";
                history.PrimaryKeyValue = Convert.ToInt32(result[2]);
                history.TableName = result[3];
                if (history.TableName == "MainRates")
                {
                    MainRate rate = MainRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
                    history.InstitutionId = rate.InstitutionId;
                }
                else if (history.TableName == "ProgramRates")
                {
                    ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
                    history.InstitutionId = rate.InstitutionId;
                }
                else
                {
                    int institutiondId;
                    if (int.TryParse(result[4], out institutiondId))
                    {
                        history.InstitutionId = institutiondId;
                    }
                    else
                    {
                        history.InstitutionId = null;
                    }
                }
                //InstitutionName and OPEID are being updated by trigger(executer after each insert operations)

                //Check if there is any modified column or not
                if (!string.IsNullOrEmpty(history.TableFields))
                    HistoryLogs.Add(history);
            }
        }

        //For Deleted columns
        var deletedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Deleted)
            .Select(t => new
            {
                Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
                objectContext = ((IObjectContextAdapter)this).ObjectContext,
                ent = t,
            });
        foreach (var item in deletedInfo)
        {
            if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
            {
                var result = GetDifference.GetDeletedValues(item.Original, item.objectContext, item.ent);
                HistoryLog history = new HistoryLog();
                history.Description = result[0];
                history.TableFields = result[1];
                history.UserId = userId;
                history.TableAction = "Deleted";
                history.PrimaryKeyValue = Convert.ToInt32(result[2]);
                history.TableName = result[3];
                if (history.TableName == "MainRates")
                {
                    int locationRateId = (int)item.Original["LocationRateId"];
                    history.InstitutionId = LocationRates.SingleOrDefault(l => l.Id == locationRateId).InstitutionId;
                }
                else if (history.TableName == "ProgramRates")
                {
                    ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
                    history.InstitutionId = rate.InstitutionId;
                }
                else
                {
                    history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
                }
                //InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
                history.InstitutionName = "";
                history.OpeidNumber = "";

                //Check if there is any modified column or not
                if (!string.IsNullOrEmpty(history.TableFields))
                    HistoryLogs.Add(history);
            }
        }
        // For data that is added
        string[] applicableTables = new string[] { "EligiblePrograms", "Fees", "LocationRates", "MainRates", "ProgramRates" };
        var addedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Added)
            .Select(t => new
            {
                Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
                ObjectContext = ((IObjectContextAdapter)this).ObjectContext,
                Entity = t,
            }).ToList();

        //Placing this here adds the primary keys to the new values before saving their history.
        Configuration.ValidateOnSaveEnabled = false;
        int rVal = base.SaveChanges();

        foreach (var item in addedInfo)
        {
            string tableName = GetTableInformation.GetTableName(item.ObjectContext, item.Entity);
            if (applicableTables.Contains(tableName))
            {
                var result = GetDifference.GetDeletedValues(item.Current, item.ObjectContext, item.Entity);
                HistoryLog history = new HistoryLog();
                history.Description = result[0];
                history.TableFields = result[1];
                history.UserId = userId;
                history.TableAction = "Added";
                history.PrimaryKeyValue = Convert.ToInt32(result[2]);
                history.TableName = result[3];
                if (history.TableName == "MainRates")
                {
                    history.InstitutionId = ((MainRate)item.Entity.Entity).InstitutionId;
                }
                else if (history.TableName == "ProgramRates")
                {
                    history.InstitutionId = ((ProgramRate)item.Entity.Entity).InstitutionId;
                }
                else
                {
                    history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
                }
                history.InstitutionName = "";
                history.OpeidNumber = "";

                //Check if there is any modified column or not
                if (!string.IsNullOrEmpty(history.TableFields))
                    HistoryLogs.Add(history);
            }
        }
        rVal += base.SaveChanges();
        return rVal;
    }
    finally
    {
        Configuration.AutoDetectChangesEnabled = autoDetectChanges;
    }
}

Then my Service class will do something like this:

        Header header = _uow.MyRepository.GetByHeaderId(model.Id, model.HeaderId);

        header.WebAddresses = string.Join(",", model.WebAddresses.ToArray());
        header.Date = DateTime.Parse(model.Date);
        header.IsField1 = model.Field1;
        header.Field2 = model.Field2;
        header.Field3 = model.Field3;

        _uow.SaveChanges();
DavidJS
  • 417
  • 2
  • 5
  • 16
  • Could you also please post your Data access code, I would like to see what is being done before calling SaveChanges – Kiran Vedula May 09 '16 at 20:50
  • 1
    Possible duplicate of [The relationship could not be changed because one or more of the foreign-key properties is non-nullable](http://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro) – James P May 09 '16 at 21:53
  • I updated my question with the SaveChanges code, I am overwriting saveChanges – DavidJS May 10 '16 at 15:20

0 Answers0