You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 7代码优先外键异常:插入时触发标识列写入错误

问题描述

确定问题出在OnModelCreating方法中,但不清楚缺失了什么配置。尝试创建两个DbSet,让SocialMediaUrls通过外键关联SocialMediaTypes,但向SocialMediaUrls插入数据时,代码却试图向SocialMediaTypes中插入内容,不符合预期。

实体类代码

public class SocialMediaUrls
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public Guid? ProfileId { get; set; }

    public SocialMediaTypes? SocialMediaTypes { get; set; }

    [Required]
    public string Url { get; set; } = string.Empty;

    [Required]
    public bool isActive { get; set; }
}

public class SocialMediaTypes
{
    [Key]
    public int SocialMediaTypesId { get; set; }

    [Required]
    public string Name { get; set; }

    public string? Url { get; set; } = string.Empty;
    public string? PlaceholderText { get; set; } = string.Empty;
    public string? IconUrl { get; set; } = string.Empty;

    [Required]
    public bool isPaymentApp { get; set; }

    [Required]
    public bool isActive { get; set; }
}

新增/更新逻辑代码

public async Task<SocialMediaUrls> AddUpdateProfileSocialMediaAsync(SocialMediaUrls ProfileSocialMedia)
{
    var foundSocialMedia = await _context.SocialMediaUrls.FirstOrDefaultAsync(e => e.Id == ProfileSocialMedia.Id);

    if (foundSocialMedia != null)
    {
        foundSocialMedia.Url = ProfileSocialMedia.Url;
        foundSocialMedia.SocialMediaTypesId = ProfileSocialMedia.SocialMediaTypesId;

        await _context.SaveChangesAsync();

        return foundSocialMedia;
    }
    else
    {
        try
        {
            var addedEntity = await _context.SocialMediaUrls.AddAsync(ProfileSocialMedia);

            await _context.SaveChangesAsync();

            return addedEntity.Entity;
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

DbContext代码

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SocialMediaUrls>().HasIndex(s => s.Id).IsUnique(true);

    modelBuilder.Entity<SocialMediaTypes>().HasIndex(s => s.SocialMediaTypesId).IsUnique(true);

    modelBuilder.Entity<SocialMediaTypes>().HasData(
            new SocialMediaTypes { SocialMediaTypesId = 1, Name = "Website", IconUrl= "Website.png", isActive = true, Url="", PlaceholderText="", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 2, Name = "Facebook", IconUrl = "Facebook.png", isActive = true, Url = "www.facebook.com/", PlaceholderText = "link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 3, Name = "Twitter", IconUrl = "Twitter.png", isActive = true, Url = "www.twitter.com/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 4, Name = "Instagram", IconUrl = "Instagram.png", isActive = true, Url = "www.instagram.com/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 5, Name = "YouTube", IconUrl = "YouTube.png", isActive = true, Url = "www.youtube.com/", PlaceholderText = "link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 6, Name = "LinkedIn", IconUrl = "LinkedIn.png", isActive = true, Url = "www.linkedin.com/in/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 7, Name = "Snapchat", IconUrl = "Snapchat.png", isActive = true, Url = "www.snapchat.com/add/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 8, Name = "TikTok", IconUrl = "TikTok.png", isActive = true, Url = "www.tiktok.com/@", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 9, Name = "Twitch", IconUrl = "Twitch.png", isActive = true, Url = "www.twitch.tv/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 10, Name = "Pinterest", IconUrl = "Pinterest.png", isActive = true, Url = "www.pinterest.com/", PlaceholderText = "link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 11, Name = "Vimeo", IconUrl = "Vimeo.png", isActive = true, Url = "www.vimeo.com/", PlaceholderText = "username or link", isPaymentApp = false },
            new SocialMediaTypes { SocialMediaTypesId = 12, Name = "CashApp", IconUrl = "CashApp.png", isActive = true, Url = "www.cash.app/$", PlaceholderText = "username or link", isPaymentApp = true },
            new SocialMediaTypes { SocialMediaTypesId = 13, Name = "Venmo", IconUrl = "Venmo.png", isActive = true, Url = "www.venmo.com/", PlaceholderText = "link", isPaymentApp = true },
            new SocialMediaTypes { SocialMediaTypesId = 14, Name = "PayPal", IconUrl = "PayPal.png", isActive = true, Url = "www.paypal.me/", PlaceholderText = "username or link", isPaymentApp = true }
        );
}

已尝试的配置

modelBuilder.Entity<SocialMediaUrls>()
                .HasOne(s => s.SocialMediaTypes)
                .WithMany()
                .OnDelete(DeleteBehavior.Restrict);

解决方案

1. 补充外键属性

在SocialMediaUrls类中显式添加外键字段,让EF Core明确关联关系:

public class SocialMediaUrls
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public Guid? ProfileId { get; set; }

    // 添加显式外键属性
    public int? SocialMediaTypesId { get; set; }

    public SocialMediaTypes? SocialMediaTypes { get; set; }

    [Required]
    public string Url { get; set; } = string.Empty;

    [Required]
    public bool isActive { get; set; }
}

2. 正确配置实体关系

在OnModelCreating中指定外键,明确关联规则:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 配置一对多关系,指定外键
    modelBuilder.Entity<SocialMediaUrls>()
        .HasOne(s => s.SocialMediaTypes)
        .WithMany()
        .HasForeignKey(s => s.SocialMediaTypesId)
        .OnDelete(DeleteBehavior.Restrict);

    // 种子数据保留不变
    modelBuilder.Entity<SocialMediaTypes>().HasData(
        // 你的种子数据...
    );
}

3. 调整新增逻辑

插入SocialMediaUrls时,只设置SocialMediaTypesId外键值,不要传入SocialMediaTypes实例(避免EF误判为新实体):

// 示例:创建新的SocialMediaUrls对象时直接用已存在的类型ID
var newSocialMedia = new SocialMediaUrls
{
    ProfileId = someGuid,
    SocialMediaTypesId = 1, // 对应已存在的SocialMediaTypesID
    Url = "https://example.com",
    isActive = true
};

await _context.SocialMediaUrls.AddAsync(newSocialMedia);
await _context.SaveChangesAsync();

如果必须传入SocialMediaTypes实例,需要先将其附加到上下文,标记为已存在:

if (ProfileSocialMedia.SocialMediaTypes != null)
{
    // 告诉EF该实体已存在,不需要插入
    _context.Attach(ProfileSocialMedia.SocialMediaTypes);
}

var addedEntity = await _context.SocialMediaUrls.AddAsync(ProfileSocialMedia);
await _context.SaveChangesAsync();

内容的提问来源于stack exchange,提问作者Dave Koppe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:58:08