C# 具有新/修改对象的上下文上的SaveChanges()不';我什么也不做

C# 具有新/修改对象的上下文上的SaveChanges()不';我什么也不做,c#,.net,entity-framework,C#,.net,Entity Framework,我曾经为我的ASP.NET站点提供了一个工作数据库,直到我了解到在整个应用程序生命周期中使用静态数据库上下文对象是一种非常糟糕的做法 所以,最初,我有这样一个: public class Database { MainDBContainer db; static Database() { db = new MainDBContainer(); } } internal sta

我曾经为我的ASP.NET站点提供了一个工作数据库,直到我了解到在整个应用程序生命周期中使用静态数据库上下文对象是一种非常糟糕的做法

所以,最初,我有这样一个:

    public class Database
    {
        MainDBContainer db;
        static Database()
        {
            db = new MainDBContainer();
        }
    }

    internal static SiteUser GetUser(string username)
    {
         return db.SiteUserSet.SingleOrDefault(u => u.Username == username);
    }
而且,正如您可能猜到的,我总是使用这个静态对象来访问/修改数据库。好吧,因为我到处都读过(静态db上下文不好),我决定将代码改为:

    internal static SiteUser GetUser(string username)
    {
        //notice no static constructor for class.

        using (MainDBContainer db = new MainDBContainer())
        {
            return db.SiteUserSet.SingleOrDefault(u => u.Username == username);
        }
    }
这段代码的问题(不是特别的“this”代码,而是修改某些内容的代码。我的意思是,我用using关键字包装了每个数据库访问,就像这个一样),
调用db.SaveChanges()
时,不会引发任何异常,但也不会发生任何事情。在同样的背景下,一切都是有效的,但仅此而已不会将任何内容写入实际的SQL数据库。之前,我已经设置好所有内容并开始工作,只要调用了
SaveChanges()
,所有内容都会立即刷新到数据库中。我的用户身份验证甚至被破坏(很简单:客户端发送用户名/密码哈希,如果其正确的服务器发送随机令牌,并且客户端在每个请求中使用令牌):用户调用login方法并成功获得令牌,但每当任何其他代码从另一个上下文与用户对象交互时,该标记是DB以前拥有的任何标记,并且登录方法中的
SaveChanges
没有任何效果。所有方法都是一样的,我只是给出了一个简单的登录示例。我错过什么了吗?在移植代码时,我是否错过了一些明显的东西?可能是的,但是是什么

谢谢,
Can。

您已移动到断开连接的型号。当一个上下文被破坏时,当您在下一个CRUD操作中创建一个新实例时,EF不再知道哪些对象是关联的。本质上,您必须手动告诉EF您想要持久化的对象以及如何持久化它们

要保存,需要在上下文中调用
AddObject

要进行更新,请调用
AttachTo
,然后在
ObjectStateManager
上调用
ChangeObjectState
SetModifiedProperty
。(注意:这仅适用于完全断开连接的对象:如果加载一个对象,然后进行更改——如果正在执行行级版本控制,则可能会执行此操作——EF已经知道该执行什么操作,因为它有一个内置的更改跟踪机制,但仅当对象连接时。)


要删除,请调用
AttachTo
,然后调用
DeleteObject

,您已移动到断开连接的模型。当一个上下文被破坏时,当您在下一个CRUD操作中创建一个新实例时,EF不再知道哪些对象是关联的。本质上,您必须手动告诉EF您想要持久化的对象以及如何持久化它们

要保存,需要在上下文中调用
AddObject

要进行更新,请调用
AttachTo
,然后在
ObjectStateManager
上调用
ChangeObjectState
SetModifiedProperty
。(注意:这仅适用于完全断开连接的对象:如果加载一个对象,然后进行更改——如果正在执行行级版本控制,则可能会执行此操作——EF已经知道该执行什么操作,因为它有一个内置的更改跟踪机制,但仅当对象连接时。)


对于delete,您可以调用
AttachTo
,然后
DeleteObject

您可以发布一个代码段来保存一个实体吗?
使用(MainDBContainer db=new MainDBContainer()){GlobalObject p=db.GlobalObjectSet.SingleOrDefault(i=>i.ID==ID);//由于在代码中前面进行了检查,p保证为非null。p.Title=Title;p.Description=Description;p.IsVisible=visible;TagObject(p,tags,usr);db.SaveChanges();//这过去工作得很好,现在不行了}
您可以在保存实体的地方发布代码段吗?
使用(MainDBContainer db=new MainDBContainer()){GlobalObject p=db.GlobalObjectSet.SingleOrDefault(i=>i.ID==ID);//由于在代码之前进行了检查,p保证p不为null。p.Title=Title;p.Description=Description;p.IsVisible=visible;TagObject(p,tags,usr);db.SaveChanges();//这以前工作得很好,现在不行了}
这是调用
SaveChanges
之前的全部内容,您仍然需要这样做。那么,我如何简化流程?或者我如何以某种方式“保持连接”?我不想在代码中的任何地方调用attachto等,我只是没有使用它。在以前的模型中,我从未在任何地方编写过attachto,甚至一次也没有,我不明白为什么会出现这种情况ange破坏了我的代码。我不是EF方面的专家,但从逻辑上讲,当你调用SaveChanges()时,它只会将您更改或创建的内容写入数据库。即使创建对象不再有效,我也会创建一个新实体,然后将其保存在同一上下文中,而不会保存。与其他上下文无关。@can:正如我所解释的,当您销毁上下文时,EF不再知道哪些对象已被持久化--您没有o请再说一遍。通常这种类型的代码进入数据层,在数据层中集中调用方法——您只需在一个位置调用
Save
方法。这种事情超出了本文讨论的范围(进行谷歌搜索应该会有所帮助)。我理解你的意思。上下文只知道它以某种方式加载的对象(通过选择、编辑、创建或删除),这是有意义的,因为db上下文无法加载整个SQL server的数据。但EF不保存我刚刚在该上下文中创建的对象并保存在同一上下文中*,这仍然是没有意义的。我在代码中的任何地方都没有使用AttachTo,它过去也可以工作,我不明白为什么它现在不能用于修改/创建对象在相同的上下文中。我把这个标记为o