0

次のように、グループとユーザーの 2 つのテーブルを想定します。

[Groups] ([Id] [int] NOT NULL, [Name] [nchar](50) NULL);
[Users] ([Id] [int] NOT NULL, [Name] [nchar](50) NULL, [GroupId] [int] NOT NULL);
FOREIGN KEY([GroupId]) REFERENCES [Groups] ([Id])

GroupId はユーザーへの外部キーです。

次に、Linq-to-SQL クラス デザイナーを使用して適切なクラスを作成し、次のクラスをプロジェクトに追加します。

public partial class Group
{
    public override int GetHashCode()
    {
        return (Id.GetHashCode());
    }

    public override bool Equals(object item)
    {
        if ((item == null) || (item is System.DBNull))
            return (false);
        else
        {
            var temp = item as Group;
            if (temp == null)
                return (false);
            else
                if (_Id.Equals(0))
                    return (_Name.Equals(temp.Name));
                else
                    return (_Id == temp.Id);
        }
    }

    partial void OnValidate(System.Data.Linq.ChangeAction action)
    {
        var dc = new DB.DataContext();

        if (action == System.Data.Linq.ChangeAction.Insert)
            if (dc.Groups.Count(o => o.Name.Equals(_Name)) != 0)
                throw new Exception("Name Already Exist On Insert");

        if (action == System.Data.Linq.ChangeAction.Update)
            if (dc.Groups.Count(o => (!o.Id.Equals(_Id) && o.Name.Equals(_Name))) != 0)
                throw new Exception("Name Already Exist On Update");
    }
}

public partial class User
{
    public override int GetHashCode()
    {
        return (Id.GetHashCode());
    }

    public override bool Equals(object item)
    {
        if ((item == null) || (item is System.DBNull))
            return (false);
        else
        {
            var temp = item as User;
            if (temp == null)
                return (false);
            else
                if (_Id.Equals(0))
                    return (_Name.Equals(temp.Name));
                else
                    return (_Id == temp.Id);
        }
    }
}

public static DB.Group f1()
{
    DB.DataContext dc = new DB.DataContext();
    if (dc.Groups.Count() == 0)
    {
        DB.Group group = new DB.Group() { Name = "admins" };
        dc.Groups.InsertOnSubmit(group);
        dc.SubmitChanges();
    }
    return dc.Groups.First();
}

public static void f2(DB.Group group, string name)
{
    DB.DataContext dc = new DB.DataContext();
    DB.User user = new DB.User() { Name = name, GroupId = group.Id, };
    dc.Users.InsertOnSubmit(user);
    dc.SubmitChanges();
}

public static void f3(DB.Group group, string name)
{
    DB.DataContext dc = new DB.DataContext();
    DB.User user = new DB.User() { Name = name, Group = group, };
    dc.Users.InsertOnSubmit(user);
    dc.SubmitChanges();
}

今電話したら

DB.Group group = f1();
f2(group, "john");
f2(group, "bob");

その後、すべてがうまくいきますが、私が電話すると

DB.Group group = f1();
f2(group, "john");
f3(group, "bob");

「挿入時に名前が既に存在する」という例外がスローされます。実際、OnValidate が呼び出され、グループ テーブルの重複した名前が検出されます。奇妙な動作は、新しいユーザーがテーブルに挿入されるときに OnValidate が呼び出されることです。どうしたの?私は間違いを犯しましたか?

4

2 に答える 2

0
Group = group,

f3 では、グループのインスタンスをユーザーに関連付けました。次に、データコンテキストにユーザーを挿入するように指示しました。ユーザーに接続されたグループがあり、データコンテキストは現在そのグループを追跡していないため、グループも挿入する必要があると想定しています。

于 2013-09-14T15:24:37.047 に答える
0

f3 で新しい DataContext を作成しているため、グループを新しいレコードとして挿入することを想定していると思います。

グループを新しい DataContext に手動でアタッチして、グループを挿入しようとしないようにすることができます。

public static void f3(DB.Group group, string name)
{
    DB.DataContext dc = new DB.DataContext();
    dc.Groups.Attach(group);
    DB.User user = new DB.User() { Name = name, Group = group, };
    dc.Users.InsertOnSubmit(user);
    dc.SubmitChanges();
}

または、メソッドごとに新しい DataContext を作成するのではなく、1 つの DataContext を作成することもできます。

于 2013-09-14T14:33:07.530 に答える