在事件插入中强制使用新 ID

Forcing a new Id on an event insert

我正在使用 Google 日历 API 并且我正在将事件从一个日历复制到另一个日历,如下所示:

CalendarService service = new CalendarService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = this.ApplicationName
            });
CalendarListResource.ListRequest calRequest = service.CalendarList.List();
calRequest.MinAccessRole = CalendarListResource.ListRequest.MinAccessRoleEnum.Owner;
CalendarList calendars = calRequest.Execute();
CalendarListEntry selectedCalendar = calendar.Items[0];

EventsResource.ListRequest eventRequest = service.Events.List(selectedCalendar.Id);
eventRequest.TimeMin = DateTime.Now;
eventRequest.ShowDeleted = false;
eventRequest.SingleEvents = true;
eventRequest.MaxResults = 50;
eventRequest.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
Events events = eventRequest.Execute();

Event currentEvent = events.Items[0];
EventsResource.InsertRequest copyRequest = service.Events.Insert(currentEvent, calendarToCopyTo.Id);
copyRequest.Execute();

效果很好....第一次。第二次,它抛出错误,因为事件 ID 在 calendarToCopyTo 上不再是唯一的(即使我删除了刚刚创建的事件并重试)。我的问题是:如何在我 "inserting" 的事件中强制生成新的 ID?我在这些行之前尝试过 currentEvent.Id = "";,但似乎没有用。

Google.Apis.Requests.RequestError The requested identifier already exists. [409] Errors [ Message[The requested identifier already exists.] Location [ - ] Reason[duplicate] Domain[global] ]

根据这个 example(.NET 的),我可能应该只创建一个新的 Event 对象(基于 currentEvent),然后将其作为参数发送到插入请求。所以这里的另一个问题是:将所有属性从一个 Event 变量(此处为 currentEvent)复制到另一个变量的最简单方法是什么?

好的,这是我学到的(以及我想出的解决方案):

首先,如果你想使用我上面的代码,你必须在初始化 copyRequest 之前调用这两行:

currentEvent.Id = "";
currentEvent.ICalUID = "";

(因为IdICalUID都用作Id,所以都需要重新设置)。 这里的重要说明:如果你稍后要用 currentEvent 调用像 UpdateRequest 这样的东西,就会有问题,因为你清除了那个对象的 ID(因为 UpdateRequest 需要 eventId 作为参数- 所以即使你之前保存了它,你也必须在初始化该请求之前再次 "re-set" Id 和 ICalUID)。 [ICalUID 本质上等于Id + "@google.com"]

我的解决方案:

我没有保存 Id 和 ICalUID,而是将其清除,复制事件,然后将它们设置回我的 UpdateRequest 之前,我创建了一个用于克隆事件的克隆方法:

private Event clone(Event eventToClone)
{
    Event result = new Event();

    foreach (PropertyInfo property in typeof(Event).GetProperties())
    {
        if (property.CanRead)
            property.SetValue(result, property.GetValue(eventToClone, null));
    }

    return result;
}

所以现在我将事件复制到另一个日历的代码变成了这样:

Event newEvent = clone(currentEvent);
newEvent.Id = "";
newEvent.ICalUID = "";
EventsResource.InsertRequest copyRequest = service.Events.Insert(newEvent, calendarToCopyTo.Id);
copyRequest.Execute();

希望这对以后的人有所帮助!

您可以使用 try catch,如果不存在则创建,否则将更新,如下所示:

try
{
    service.Events.Insert(newEvent, calendarId).Execute();
}
catch (Exception)
{
    service.Events.Update(newEvent, calendarId, newEvent.Id).Execute();
}

在我的解决方案中它工作得很好。