1

膨大なコードを恐れないでください。問題は一般的です。問題をよりよく理解するためにコードを提供しました。

多対多の関係を持つテーブルを操作する標準的なアプローチを見つけようとしています。そして、私はほとんど終わりました。ここTeacherに とCourseM:M の関係があります。クラスを次のように設計しました。

Teacher- クラス:

public class Teacher
{
    public int ID{get;set;}
    public string TeacherName{get;set;}
    private List<Course> _items = null;
    public List<Course> Items
    {
        get 
        {   if (_items == null) {_items = Course.GetCoursesByTeacherID(_ID);}
            return _items;
        }
        set {_items = value;}
    }
    public int Save() 
    {   //...
        CourseTeacher.DeleteCoursesByTeacherID(tc, id);
        CourseTeacher.SaveCoursesWithTeacherID(tc, id, this.Items);
        //...
    }
    public bool Update()
    {   //...
        CourseTeacher.DeleteCoursesByTeacherID(tc, this.ID);
        CourseTeacher.SaveCoursesWithTeacherID(tc, this.ID, this.Items);
        //...
    }
    public static Teacher Get(int id)
    {   //...
        item.Items = CourseTeacher.GetCoursesByTeacherID(tc, item.ID);//...
    }
    public static List<Teacher> Get()
    {   //...
        items[i].Items = CourseTeacher.GetCoursesByTeacherID(tc, items[i].ID);//...
    }
    public static List<Teacher> GetTeachersByCourseID(int id)
    {   //...
        items = CourseTeacher.GetTeachersByCourseID(tc, id);//...
    }
    public bool Delete()
    {   //...
        CourseTeacher.DeleteCoursesByTeacherID(tc, this.ID);//...
    }
}

CourseTeacher- クラスとまったく同じです。マッピング クラスは次のとおりです。

public class CourseTeacher
{
    public int CourseID{get;set;}
    public int TeacherID{get;set;}  
    public static void SaveCoursesWithTeacherID(TransactionContext tc, int teacherID, List<Course> items){}
    public static void SaveTeachersWithCourseID(TransactionContext tc, int courseID, List<Teacher> items){}
    private void Save(TransactionContext tc){}
    public static void DeleteCoursesByTeacherID(TransactionContext tc, int teacherID){}
    public static void DeleteTeachersByCourseID(TransactionContext tc, int courseID){}
    public static List<Teacher> GetTeachersByCourseID(TransactionContext tc, int courseID){}
    public static List<Course> GetCoursesByTeacherID(TransactionContext tc, int teacherID){}
}

今私の問題は、このコードが機能していないということですか?

Teacher professorXyz = Teacher.Get(2);                        
Course cpp = Course.Get(3);
Course java = Course.Get(2);
professorXyz.Items.Remove(cpp);
professorXyz.Items.Remove(java);
professorXyz.Update();

おそらく一致が見つからないか、get アクセサーが読み取り専用リストを返しているため、これは機能していません。

これを達成するには、教師/コース - クラスをどのようにリファクタリングする必要がありますか?

例外なし。永続化コードに問題はありません。アイテムは削除されていません。

なぜprofessorXyz.Items.Contains(cpp);false を返すのですか?

何をチェックしますか?

4

5 に答える 5

4

これは直接的な答えではありませんが...

あなたのデザインは非常に(非常に)リレーショナルです。これにより、DB への永続化が容易になりますが、適切な OO モデルがありません。おそらく、DataSet で DataTables を使用することを検討し、Relation クラスの利点を享受する必要があります。


ショットを撮るには:

Teacher professorXyz = Teacher.Get(2);                        
Course cpp = Course.Get(3);

cpp コースが 2 回読み込まれ、そのコースの 2 つのインスタンスがメモリにあると思われます。あなたの設計の非常に悪い結果。デフォルトでは、これら 2 つのインスタンスは等しくないため、Remove機能しません。をオーバーロードすることもできますがEquals==それGethashCode変更可能な型にはお勧めできません
本当に必要なのは、特定の教師またはコースに対して、メモリ内に複数のインスタンスが存在しない設計です。

再コメント: オブジェクト指向の MxM 関係は次のようになります。

class Teacher
{
   public readonly List<Course> Courses = ...;
}

class Course
{
   public readonly List<Teacher> Teachers = ...;
}

これにより、DB への書き込みに少し手間がかかりますが、他の多くの問題が解決されます。

于 2009-10-18T11:03:48.257 に答える
1

ヘンクは正しいです。あなたのデザインは非常に関係性があります。ただし、この種のシナリオでは、オブジェクトの動作に注目し、オブジェクト リレーショナル マッピング (ORM) ツールを使用してオブジェクトとデータベースの間を変換することをお勧めします。

ADO.NET の DataTable と DataSet は、実際にはオブジェクト リレーショナル マッピング機能を提供しません。それらは基盤となるデータベース スキーマと密接に結び付いているため、実際には教師やコースの観点から考えたいときに、列、テーブル、およびリレーションの観点から考える必要があります。

このシナリオについては、 Castle ActiveRecordを検討することを強くお勧めします。それはあなたの例と同じアプローチを使用します-静的な Teacher.Get() を使用してインスタンスを取得し、 myTeacher.Save() を使用して変更を保存しますが、例に欠けている必要な複雑さがたくさんあり、ORMフレームワークを使用すると許可されますこの複雑さを無視して、自分のプロジェクトの要件に集中してください。

Castle ActiveRecord のドキュメントにある多対多の関連付けの例を次に示します。

于 2009-10-18T11:48:43.397 に答える