1

まず、私は ADO.NET、LINQ、およびそれらのデータ アクセス テクノロジに非常に慣れていません。私が読んでインターネットで見つけたものを理解している限り、LINQ2SQLはLINQに進化し、エンティティはADO.NETに進化しました。多分私はそれらの概念に間違っているので、私に知らせてください。

今質問に。学校を管理するために、ADO.NET を使用して VS2010 (.NET 4.0) でシステムを開発しています。このソリューションは、プレゼンテーション層 (GUI のみ)、ビジネス層 (すべてのプロセスがここで行われる)、データ層 (クエリとデータベース アクセスのみ) の 3 つの層に分かれています。

データベースには、人 (学生、教師、管理者など) のデータを格納するテーブル People があり、これまでにすべての既存の国を含む Countrys テーブルへの参照を格納する Nationality のフィールドがあります。

最初のアプローチでは、接続文字列とデータベース モデル (ADO.NET エンティティ データ モデル デザイナーによって生成されたコード) への参照を格納する ConnectionManager というシングルトン クラスを作成しました。これは、SystemEntities という ObjectContext から継承するオブジェクトです。

この時点ですべてが正常に起動しましたが、次のシナリオについて疑問に思いました: 借主が到着し、支払いの請求書を要求したときに、ユーザーが個人情報を編集しています。次に、ユーザーは請求書フォームに切り替え、データを入力し、印刷前に保存します。このプロセス中に 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

クラスで、およびコンストラクターで使用するときに、グローバルオブジェクト「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 に答える