将序列化的Entity Framework对象放回数据库中

时间:2015-06-12 18:29:05

标签: c# sql-server entity-framework

我是EF新手,无法反序列化对象,然后将其放回SQL Server Express(2014)数据库中。对于这个演示,我只有两个表,"患者"和"会议"。患者有0个或更多会话。这个想法是允许用户将会话导出到磁盘。稍后,他可能想把它放回数据库中。

我已将我的代码放在下面。我创建了2个实体(Patient和Session),将它们保存到DB。我检查过他们在那里。然后我序列化Session,然后删除Session。然后我(成功)反序列化会话。然后我打电话给:

context2.Sessions.Add(session2); 
context2.SaveChanges();  

在SaveChanges行上,我收到一个异常通知我:

System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_Patient'. Cannot insert duplicate key in object 'dbo.Patient'. The duplicate key value is (9749184b-380b-438a-a2fe-80413c3a616a).

有人可以告诉我我做错了什么吗?我应该使用'附加'而不是'添加'?它确实看起来像是在尝试重新创建患者条目。理想情况下,如果它已保存到已具有该特定患者的数据库(由主键PatientGUID决定),则应使用该数据库。如果患者没有患者,则应该创建一个。有人可以让我去吗?如果我能以不同的形式提供更多信息或信息,请告知我们。

我已在下面发布了代码和表格布局。

谢谢, 戴夫

static void Main(string[] args)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        using (PlayContext context = new PlayContext())
        {

            try
            {

                Patient pt = new Patient();
                Guid ptGuid = Guid.NewGuid();
                pt.PatientGUID = ptGuid;
                pt.PatientNumber = 1;


                Session session = new Session();
                session.SessionGUID = Guid.NewGuid();
                session.SessionNum = 101;
                pt.Sessions.Add(session);

                context.Patients.Add(pt);

                context.SaveChanges();



                try
                {
                    formatter.Serialize(stream, session);
                }
                catch (Exception ex)
                {
                    int x = 1;
                }
                context.Sessions.Remove(session);
                context.SaveChanges();


            }
            catch (Exception ex)
            {

            }

        }
        using (PlayContext context2 = new PlayContext())  // I use a new context as we'd often be getting entity back from file weeks later and from different program
        {
            try
            {
                stream.Seek(0, SeekOrigin.Begin);
                Session session2 = (Session)formatter.Deserialize(stream);
                context2.Sessions.Add(session2);
                context2.SaveChanges();
            }
            catch (Exception ex)
            {

            }
        }
    }

对于这两张桌子,我有

Patient Table
PatientGUID uniqueidentifier NOT Allow Nulls  Primary Key
PatientNumber int  NOT Allow Nulls

Session Table
SessionGUID   uniqueidentifier NOT Allow Nulls Primary Key
PatientGUID   uniqueidentifier NOT Allow Nulls  (foreign key to PatientGUID in patient table)

SessionNum int NOT Allow Nulls

Insert and Update Specific for Session Table are set to 'Cascade'

2 个答案:

答案 0 :(得分:1)

我会考虑制作"保存/更新" EF条件中的函数基于实体ID。示例模板可能如下所示:

Session SaveSession(Session input) {
    using(var context = new DbContext()){
        if(input.ID != 0) {
            // Entity exists, modify the original
            var mySession = context.Sessions.Find(input.ID);
            mySession.Name = input.Name;
            mySession.Color = input.Color;
            // Etc.

            // Make sure that foreign keys are pulled from current context and not duplicated
            mySession.Patient = context.Patients.Find(input.Patient.ID);

            context.Entry(mySession).EntityState = EntityState.Modified;
        } else {
            // Entity does not exist, add fresh

            // Make sure that foreign keys are pulled from current context and not duplicated
            input.Patient = context.Patients.Find(input.Patient.ID);

            context.Add(input);
        }

        context.SaveChanges();
        return input;
    }
}

在处理非常复杂的数据模型时,这个模板会变得非常混乱,但是我发现它很清楚地告诉EntityFramework你想要它做什么。至少,我希望这可以帮助您解决重复问题!

另一个提示是,EF会自动为具有空public int ID属性的实体分配ID,因此您无需手动设置。这是关于此的Stack问题:How to generate and auto increment Id with Entity Framework

答案 1 :(得分:0)

实体框架不适用于已脱位的实体,并且您的代码实体并不知道​​您的患者存在于数据库中,因此也尝试插入患者。

在将会话添加到上下文之前尝试添加context2.Patient.Attach(session2.Patient);