如何使用事件接收器同步两个不同 SPSite 中的两个列表?

How to synchronize two lists in two different SPSites using Event Receivers?

我有两个具有相同列表名称和相同列的网站。现在我想创建项目更新事件接收器,其中当用户更新列表 1 中的任何列表项时,它应该在列表 2 中更新。用户可以在两个列表中创建一个新项目。

using (SPSite site = new SPSite("url"))
                using (SPWeb webWList = site.OpenWeb())
                {
                    SPList targetList = web.Lists["listTitle"];
                     string ID = properties.ListItem[""].ToString();
                    string internalColNAme = properties.ListItem.Fields["ColNAme"].InternalName.ToString();


                    SPQuery query = new SPQuery();
                    query.Query = "<Query><Where><Eq><FieldRef Name=''/><Value Type='Number'>" + properties.ListItemId + "</Value></Eq></Where></Query>";

                    SPListItemCollection items = targetList.GetItems(query);

                    SPListItem item = items[0];

                    item["ColName"] = properties.ListItem[""];
                    item.Update();           
                }
            });

事件接收器工作正常,但它更新了错误的项目。

也许您想看看 this tutorial

在 ItemAdded 事件中,从其他 SPSite 获取列表并使用 SPList.AddItem() 方法在其中添加项目。为了确保足够的访问权限 运行 它具有提升的权限。

ItemAdded 方法中的一些示例代码

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using(SPSite siteWhereNewItemWillBeAdded = new SPSite("url of web with list 2"))
    using(SPWeb webWithList = siteWhereNewItemWillBeAdded.OpenWeb())
    {
        SPList targetList = webWithList.Lists["listTitle"];
        SPListItem newItem = targetList.AddItem();
        //Set properties of item
        newItem["column of list 2"] = properties.ListItem["column of list 1"]
        newItem.Update();
    }
});

将字符串替换为所描述的内容,如果您有更多 columns/fields 要复制到列表 2 中的项目,请添加更多设置属性行。

更新要求是另一回事,您需要保存列表 1 中的哪个项目属于列表 2 中的哪个项目。否则您将无法告诉要更新的项目,除非您有一些唯一的字段并且在两个表中相等。

要实现这一点,您可以将自定义列添加到 list2。假设自定义列名为 "list1Item".

在 ItemUpdated 事件中,您将拥有:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using(SPSite siteWhereNewItemWillBeAdded = new SPSite("url of web with list 2"))
    using(SPWeb webWithList = siteWhereNewItemWillBeAdded.OpenWeb())
    {
        SPList targetList = webWithList.Lists["listTitle"];
        var list2Items = targetList.Items;
        var syncedItem = from SPListItem item in list2Items 
                         where Convert.ToString(item["list1Item"]).Equals(properties.ListItem.ID.ToString()) 
                         select item;
        //Set properties of item
        syncedItem["column of list 2"] = properties.ListItem["column of list 1"]
        syncedItem.Update();
    }
});

要映射项目,请将此行添加到您设置列值的 ItemAdded 事件。

newItem["list1Item"] = properties.ListItem.ID;

更新:匹配问题更新

这是项目更新事件的 SPSecurity 上下文中的完整代码吗? 你用这些变量做什么?

string ID = properties.ListItem["Zone"].ToString();
string internalColNAme = properties.ListItem.Fields["ColNAme"].InternalName.ToString();

根据我目前的理解,您正在尝试将 list1 中第 "Zone" 列中的项目内容写入 list2 中第 "ColName" 列中的项目。这些项目使用 list2 中的 "Mapping" 列进行匹配。您的 ItemAdded 方法是否包含以下行的任何版本?

newItem["Mapping"] = properties.ListItemId;

你说更新错了。列表 2 中是否有超过 1 项具有相同 "Mapping" 内容?您的代码只会更新查询找到的第一个代码。

using (SPSite site = new SPSite("url"))
                using (SPWeb webWithList = site.OpenWeb())
                {
                    SPList targetList1 = webWithList.Lists["listTitle"];
                     string ID = properties.ListItem["Zone"].ToString();
                    string internalColNAme = properties.ListItem.Fields["ColNAme"].InternalName.ToString();


                    SPQuery query = new SPQuery();
                    query.Query = "<Where><Eq><FieldRef Name='Mapping'/><Value Type='Number'>" + properties.ListItemId + "</Value></Eq></Where></Query>";

                    SPListItemCollection items = targetList1.GetItems(query);

                    SPListItem item = items[0];

                    item["ColName"] = properties.ListItem["Zone"];
                    item.Update();           
                }
            });