如何使用事件接收器同步两个不同 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();
}
});
我有两个具有相同列表名称和相同列的网站。现在我想创建项目更新事件接收器,其中当用户更新列表 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();
}
});