如何在更新ADO.NET生成的实体时访问ObjectContext对象

时间:2012-10-24 01:13:04

标签: c# linq ado.net linq-to-entities

首先,我是ADO.NET,LINQ和那些数据访问技术的新手。据我所知,我在互联网上发现了什么,LINQ2SQL演变为LINQ到演变为ADO.NET的实体。也许我对这些概念不对,所以请告诉我。

现在回答这个问题。我正在使用ADO.NET在VS2010(.NET 4.0)中开发一个系统来管理学校。该解决方案分为3层:表示层(仅GUI),业务层(此处完成所有流程)和数据层(仅查询和数据库访问)。

数据库有一个表人员用于存储人员(学生,教师,行政等)的数据,其中包含国籍字段,该字段存储了所有现有国家/地区对“国家/地区”表的引用。

在我的第一个方法中,我创建了一个名为ConnectionManager的单例类,它存储连接字符串和对数据库模型的引用(由ADO.NET实体数据模型设计器生成的代码),一个继承自ObjectContext的对象,称为SystemEntities

此时一切都很好,但是我想知道以下情况:当客户到达时,用户正在编辑人员信息并请求支付账单;然后用户切换到账单表格,填写数据并在打印前保存。在此过程中,调用SystemEntities.SaveChanges以便将所有更改保存到数据库中,然后保存对已编辑人员所做的未完成更改,但这是一种不良行为。

然后我开始说我必须没有一个能够保持与数据库的连接打开的单例。每个ObjectContext都可以在获取数据之后处理,因此应该使用像这样的代码。

要抓取所有人

public static T[] QueryAll<T>() where T : Person
{
    using (SystemEntities context = ConnectionManager.Instance.GetContext())
    {
        return context.People
            .OfType<T>()
            .Include("Emails")
            .Include("Phones")
            .OrderBy(affiliate => affiliate.LastName + " " + affiliate.FirstName)
            .ToArray();
    }
}

获取国家/地区

public static Country GetByID(string id)
{
    using (SystemEntities context = ConnectionManager.Instance.GetContext())
    {
        return context.Countries.FirstOrDefault(country => country.CountryID == id);
    }
}

现在,当我尝试编辑一个人时,要具体改变一个人的国家,就会出现异常:

The relationship between the two objects cannot be defined
because they are attached to different ObjectContext objects.

这可以通过以下代码完成:

public Person Person
{
    get { ... }
    set
    {
        this.person = value;
        ...
        this.cmbNationality.DataBindings.Add("SelectedItem", person, "Nationality");
        this.cmdAddressCountry.DataBindings.Add("SelectedItem", person, "Country");
        ...
    }
}

private void form_Load(object sender, EventArgs e)
{
    Country[] countries = Country.QueryAll();
    Country mexico = Country.GetByA2("MX");
    this.cmbNationality.DataSource = countries;
    this.cmdAddressCountry.DataSource = countries;
    this.cmbNationality.SelectedItem = mexico;
    this.cmdAddressCountry.SelectedItem = mexico;
}

因此,当您更改cmbNationality和cmdAddressCountry组合框中的项目时,将引发异常。请注意,这只是一个更改,没有执行保存。

据我所知,这是因为Person和Country对象是从不同的SystemEntities(ObjectContext)对象从数据库中提取的。

还有问题和疑问。如果我不能使用单例并且所有上下文必须在使用后丢弃,我该如何解决?当然我可以创建几个方法来避免这个问题,手工更新或不使用数据绑定,但是,如果你必须手头有更新,那么ADO.NET有什么意义呢?

可能是一个愚蠢或微不足道的(或者我可能只是不知道如何搜索答案)问题,但我无法找到答案。

提前致谢

2 个答案:

答案 0 :(得分:1)

为什么不在类中设置全局对象“System Entities context”,在构造函数中使用\

"context = ConnectionManager.Instance.GetContext()",所以你会得到相同的

SystemEntities (ObjectContext) objects.

我希望它可以帮到你。

答案 1 :(得分:1)

听起来你正在使用标准的断开模型。由于您已断开连接,因此只要持久保存修改后的对象,您就必须从当前上下文中重新保存实体。以下希望更能说明我的意思:

    public static Person PersistPerson(Person person)
    {
        using (SystemEntities context = ConnectionManager.Instance.GetContext())
        {
            bool doInsert = false;
            var p = context.People.Where(d => d.PersonId == person.PersonId).FirstOrDefault();
            if (p == null)
            {
                p = new Person();
                doInsert = true;
            }

            //update connected Entity
            p.LastName = person.LastName;
            p.Emails = person.Emails;
            //etc...
            if(doInsert)                    
                context.People.AddObject(person);

            context.SaveChanges();
            person.PersonId = p.PersonId;
        }
        return person;
    }