1

Windowsフォームアプリにチェックリストボックスがあり、ユーザーは1つ以上のセキュリティグループを選択したユーザーに割り当てることができます。

WCF Data Servicesを使用すると、問題なくボックスにデータを入力できます。ただし、ユーザーがボックス内の選択を変更してそれらの変更を保存しようとすると、問題が発生します。

これが私の論理を説明するコメント付きのコードです。

private void ProcessSecurityGroupSelection_Original()
{
  //Get a reference to the selected user, including the associated SecurityGroups.
  var user = _ctx.Users
    .AddQueryOption("$filter", "UserID eq " + ((DataService.User)lstUsers.SelectedItem).UserID)
    .AddQueryOption("$expand", "SecurityGroups")
    .First();

  //Remove all the SecurityGroups so we can replace them.
  user.SecurityGroups.Clear();

  foreach (var selectedGroup in lstSecurityGroups.CheckedItems)
  {
    //Loop through the selected SecurityGroups, linking and adding each SecurityGroup to the User object.
    var securityGroup = (from sg in _ctx.SecurityGroups
                 where sg.SecurityGroupID == ((DataService.SecurityGroup)selectedGroup).SecurityGroupID
                 select sg).First();

    _ctx.AddLink(user, "SecurityGroups", securityGroup);

    user.SecurityGroups.Add(securityGroup);
  }

  _ctx.UpdateObject(user);
  _ctx.SaveChanges();
}

以前に選択されたSecurityGroupのAddLinkメソッドにコードがヒットすると、「コンテキストはすでに関係を追跡しています」というエラーが表示されます。Clear()メソッドがコンテキスト内のリンクを削除するようには見えません。

既存のリンクを削除するにはどうすればよいですか、またはこれにすべて間違ってアプローチしていますか?

4

3 に答える 3

2

Silverlight プロジェクトでも同じ問題が発生しました。私のために働いた解決策を取り、それをあなたの User/SecurityGroup モデルに適用しました。

ユーザー クラスに以下を追加します。

public User()
    {
    this.SecurityGroups.CollectionChanged += (sender, e) =>
        {
        if (e.Action == Add)
            {
            foreach (SecurityGroup AddedGroup in e.NewItems)
            AddSecurityGroup(AddedGroup);
            }
        if (e.Action == Remove)
            {
            foreach (SecurityGroup RemovedGroup in e.OldItems)
            RemoveSecurityGroup(RemovedGroup);
            }

        };

    ..... rest of constructor
    }



public void AddSecurityGroup(SecurityGroup secGroup)
    {
    LinkDescriptor descriptr = _ctx.GetLinkDescriptor(this, "SecurityGroups", secGroup);

    if (descriptr == null)
        _ctx.AddLink(this, "SecurityGroups", secGroup);

    else if (descriptr.State == EntityStates.Deleted)
        _ctx.DetachLink(this, "SecurityGroups", secGroup);

    }


public void RemoveSecurityGroup (SecurityGroup secGroup)
    {
    LinkDescriptor descriptr = _ctx.GetLinkDescriptor(this, "SecurityGroups", secGroup);

    if (descriptr == null)
        {
        _ctx.AttachLink(this, "SecurityGroups", secGroup);
        _ctx.DeleteLink(this, "SecurityGroups", secGroup);
        }

    else if (descriptr.State == EntityStates.Added)
        _ctx.DetachLink(this, "SecurityGroups", secGroup);

    else
        _ctx.DeleteLink(this, "SecurityGroups", secGroup);

    }

次の行を削除します。

_ctx.AddLink(user, "SecurityGroups", securityGroup);  

上記のコードから。

于 2012-10-04T18:33:02.573 に答える
1

リンクを削除する 1 つの方法は、次のようなイベントを追加することです。

private void lstSecurityGroups_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if (e.NewValue == CheckState.Unchecked)
    {
        _ctx.DetachLink(user, "SecurityGroups", securityGroup);
    }
    else if (e.NewValue == CheckState.Checked)
    {
        _ctx.AddLink(user, "SecurityGroups", securityGroup);
    }
}

DeleteLinkエンティティにも削除のマークを付けることに注意してください。複数回呼び出すとエラーが発生します。リンクを削除したいだけの場合は、 を使用してくださいDetachLink

于 2012-07-05T17:24:32.740 に答える