ASP.NET C# Entity Framework - How to update Foreig

2019-08-03 00:54发布

问题:

I'M quite new to this EF but I think I'M making progress. Anyway, it appears I do NOT know how to Update an object that is RELATED by a Foreign Key.

My DbRelation is:

And I'm trying to UPDATE the one members LANGUAGEID and here is the Context I invoke:

public class ManagerBase
    {
        private static NoxonEntities _entities = null;

        public NoxonEntities Entities
        {
            get
            {
                if (_entities == null)
                    _entities = new NoxonEntities();

                return _entities;
            }
        }
    }

There are many things I have tried. Here is one:

1)

MemberManager currentMemberManager = new MemberManager();
var Mem = currentMemberManager.MyEntities.Member.SingleOrDefault(c => c.Id == 2);
var Lang = currentLanguageManager.Entities.Language.SingleOrDefault(c => c.Id == 1);

            Mem.Language = Lang;
//Or
            Mem.LanguageId = Lang.Id;
currentMemberManager.Save(Mem);

In appreach 1, I get an error like

The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.

2)

//Managers uses ManagerBase class as a Base class
MemberManager currentMemberManager = new MemberManager();
currentMemberManager.Save(Globals.CurrentMember.Id, Globals.CurrentLanguage.Id);
//These Global objects coming from a Http Session
//You may also say not to keep whole member object in session which I'll not after I figure this out

Here is my SAVE method and where I have the actual problem:

public void Save(Member entity)
        {
            var Data = base.Entities.Member.First(c => c.Id == entity.Id);
                    if (Data != null)
                    {
                        Data = entity;
                        base.Entities.SaveChanges();
                    }
                }
            }

In appreach 1, I get an error in this code in EF model edmx file

[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
        [DataMemberAttribute()]
        public global::System.Int32 LanguageId
        {
            get
            {
                return _LanguageId;
            }
            set
            {
                OnLanguageIdChanging(value);
                ReportPropertyChanging("LanguageId");
                _LanguageId = StructuralObject.SetValidValue(value);
                ReportPropertyChanged("LanguageId");
                OnLanguageIdChanged();
            }
        }

And the error is

Object reference not set to an instance of an object.

Clearly I'm in the wrong way with EF.

Could you please help me and show how to properly Update a relation Id (ForeignKeyId) ?

Thank you so much.

回答1:

Yes, you are using EF in many wrong ways. First, as Arran points out, you should never make your data context static. I know that seems easier, but it's a huge problem because data contexts are designed to be created and destroyed frequently.

If you don't, then the object graph continues to grow until the app pool is eventually exhausted, plus you can run into all kinds of problems with concurrent access. Static objects are shared between all threads, so imagine if two users are using your app at the same time, they will both be using the same data context and would stomp all over each other.

Second, you're using a singleton, which is one of the most reviled patterns there are, for a lot of reasons. They have their uses, but they're far more rare than most people use them.

Third, based on the error messages, it sounds like your data model may not be in sync with your EF model, and thus it's getting confused and throwing exceptions. Have you made changes to your database structure without updating your ef model? Bear in mind that regenerating doesn't always update everything, and sometimes you have to either update it manually, or delete your objects and re-add them.

Fourth, your real problem (trust me, the ones I've laid out are also real problems, that WILL bite you in the rear at some point) lies in this code:

var Data = base.Entities.Member.First(c => c.Id == entity.Id);
if (Data != null)
{
    Data = entity;
    base.Entities.SaveChanges();
}

The first thing you have to realize is that EF returns tracked objects, these objects have references in EF and track the changes that occur. What you are doing here is getting an object, and then throwing it away and replacing it with a non-tracked object that was passed in.

You have to update the object returned from the First method, and not replace it with a new one.