Entity Framework Code First - Невозможно вставить дубликат ключа в объект 'dbo.T_CRProviders' - PullRequest
4 голосов
/ 12 марта 2012

У меня есть срочная проблема, на которую я не смог найти ответ в Интернете.

Я использую CodeFirst EF 4.3.1 и получаю сообщение об ошибке: Violation of PRIMARY KEY constraint 'PK_T_CRProviders'. Cannot insert duplicate key in object 'dbo.T_CRProviders'.

Мойкод:

Модели:

public enum CRProviderEnums
{
    PE_Abcd = 0,
    PE_Efgh
}

[Table("T_CRProviders")]
public class CRProvider
{
    [Key]
    [Required]
    public int Enum { get; set; }
    [Required]
    public string Name { get; set; }
}

[Table("T_CRSupportedResources")]
public class CRSupportedResource
{
    [Key]
    public Guid SupportedResourceId { get; set; }
    [Required]
    public CRProvider Provider { get; set; }
}

DbContext:

public class RSContext : DbContext
{
    public DbSet<CRProvider> CRProviders { get; set; }
    public DbSet<CRSupportedResource> CRSupportedResources { get; set; }
}

Таблица T_CRProviders выглядит следующим образом: Enum (PK), Name

Таблица T_CRSupportedResources выглядит такthis: SupportedResourceId (PK), Provider_Enum (FK).

В таблице базы данных T_CRProviders у меня уже есть провайдер со следующими значениями:

Enum: 0 (which is PE_Abcd)
Name: "PE_Abcd"

Теперь мой main () вызывает метод AddSupportedResource.Этот метод добавляет в таблицу T_CRSupportedResources новый CRSupportedResource, который ссылается на провайдера 0 (PE_Abcd).Метод выглядит следующим образом:

public void AddSupportedResource()
    {
        CRSupportedResource supportedResource = new CRSupportedResource()
        {
            SupportedResourceId = Guid.NewGuid(),
            Provider = new CRProvider()
            {
                Enum = (int)CRProviderEnums.PE_Abcd,
                Name = "PE_Abcd"
            }
        };

        using (RSContext myContext = new RSContext())
        {
            myContext.CRSupportedResources.Add(supportedResource);

            myContext.SaveChanges();
        }
    }

Я ожидаю, что этот метод оставит таблицу T_CRProviders без изменений и добавит новую строку в таблицу T_CRSupportedResources, которая будет выглядеть следующим образом:

SupportedResourceId: DE532083-68CF-484A-8D2B-606BC238AB61
Provider_Enum (FK): 0 (which is PE_Abcd).

Вместо этогопосле SaveChanges платформа Entity также пытается добавить Provider в таблицу T_CRProviders, и, поскольку такой поставщик уже существует, он выдает следующее исключение:

An error occurred while updating the entries.

Violation of PRIMARY KEY constraint 'PK_T_CRProviders'. Cannot insert duplicate key in object 'dbo.T_CRProviders'.

The statement has been terminated.

Мой вопрос:

Как я могу указать EF не обновлять таблицу T_CRProviders после обновления таблицы T_CRSupportedResources?

Кстати, в SQL Server я вижу, что таблица T_CRSupportedResources имеет внешний ключ с именем FK_RW_TCRSupportedCloudResources_RW_TCRCloudProviders_Provider_Enumи его правило обновления имеет значение No Action.

Ответы [ 2 ]

6 голосов
/ 12 марта 2012

Я ожидаю, что этот метод оставит таблицу T_CRProviders нетронутой и добавит новую строку в таблицу T_CRSupportedResources

Нет, этого не произойдет.Вы создаете отдельный граф сущностей, состоящий из существующей сущности А и новой сущности.EF не будет знать о существовании вашей сущности, пока вы не проинформируете ее об этом - нет никаких запросов в БД, подтверждающих существование, выполненных EF за.

Если вы вызываете метод Add, все сущности в вашем графе сущностейдобавляются как новые.Если вы не хотите вставлять их все, вы можете начать с использования Attach и вручную изменить состояние для новых.Например, как:

myContext.CRSupportedResources.Attach(supportedResource);
myContext.Entry(supportedResource).State = EntityState.Added;
0 голосов
/ 03 июля 2012

На самом деле, есть способ сделать это.

См. Ответ на мой вопрос по следующей ссылке:

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/62f3e5bc-c972-4622-b830-e7d7fe710101

...