1

首先,我对 ADO.NET、LINQ 和那些数据访问技术非常陌生。据我了解,我在 Internet 上阅读和发现的内容 LINQ2SQL 演变为 LINQ 到演变为 ADO.NET 的实体。也许我对这些概念有误,所以让我知道。

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

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

在我的第一种方法中,我创建了一个名为 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 的意义何在?

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

提前致谢

4

2 回答 2

1

为什么不在类中以及在构造函数中使用时设置 gobal 对象“SystemEntities 上下文”

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

SystemEntities (ObjectContext) objects.

我希望它可以帮助你。

于 2012-10-24T01:42:53.367 回答
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;
    }
于 2012-10-24T02:33:20.013 回答