У меня есть следующий код:
// accessedKeys is a HashSet<string>
if (accessedKeys.Count > 0)
{
string queryFormat = @"SET NOCOUNT ON;
DECLARE @updated_resources TABLE (name varchar(512))
INSERT INTO @updated_resources (name) VALUES ('{0}')
MERGE resource_access WITH (HOLDLOCK) AS target
USING @updated_resources AS source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET last_access = GETDATE()
WHEN NOT MATCHED THEN
INSERT (name, last_access) VALUES (source.name, GETDATE());";
string entries = String.Join("'),('", accessedKeys.Select(s => s.Replace("'", "''")));
string query = String.Format(queryFormat, entries);
using (var connection = new SqlConnection(...))
{
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
accessedKeys.Clear();
}
resource_access
создается как таковой:
CREATE TABLE resource_access (
name varchar(512) primary key,
last_access smalldatetime not null
)
С перерывами я получаю следующее исключение во время выполнения моего заявления:
The MERGE statement attempted to UPDATE or DELETE the same row more than
once. This happens when a target row matches more than one source row. A
MERGE statement cannot UPDATE/DELETE the same row of the target table
multiple times. Refine the ON clause to ensure a target row matches at most
one source row, or use the GROUP BY clause to group the source rows.
@updated_resources.name
заполняется из списка различных строк, а resource_access.name
- это первичный ключ, что означает, что он также уникален. Я объединяюсь в столбец name
обеих таблиц, и ни одна из них не может иметь дублируемую запись.
Если я нарушаю исключение, accessedKeys.Distinct().Count
равен accessedKeys.Count
. Если я выполняю SELECT COUNT(DISTINCT(name)) FROM resource_access
, он равен количеству строк в таблице.
Почему я иногда получаю эту ошибку?
Вы проверили, что имена отличаются от поиска без учета регистра? С#, который вы указали для поиска различных значений, зависит от регистра. В зависимости от настроек, которые вы установили в своей базе данных, MERGE будет делать свой регистр поиска нечувствительным. Таким образом, если ваша таблица имеет имя "Боб", и ваши входящие данные имеют как "Боб", так и "BOB", вы получите эту ошибку.
Попробуйте это вместо этого:
accessedKeys.Distinct(StringComparer.CurrentCultureIgnoreCase).Count()