首页 > 解决方案 > 在 Entity Framework Core 中插入没有 PK 的表

问题描述

我目前正在使用 .NET Core 3.1,我想将我的一些数据集成到现有应用程序中。这个应用程序最初使用 SQL Server 作为数据库我想使用 SSIS 将我的数据集成到这个应用程序中,但我只知道他们使用的是 SQL Server Express,所以我不能使用 SSIS。

因此,我决定创建一个 hangfire 作业来获取我的数据(多个来源)并使用 EF Core 将其插入到现有应用程序中。但是现在我只知道该表没有 PK,因为它已经运行了很长一段时间并且不是我的应用程序,我不能只将 pk 添加到表中。当我尝试使用 EF Core 插入它时出现此错误

System.InvalidOperationException:'无法跟踪'T1Item'类型的实例,因为它没有主键。只能跟踪具有主键的实体类型。

这是我的代码:

using (var scope = scopeFactory.CreateScope())
{
    var db1 = scope.ServiceProvider.GetRequiredService<db1Context>();
    var db2 = scope.ServiceProvider.GetRequiredService<db2Context>();

    var stagingTableConfig = db1 .KreTableFlagConfiguration.Where(x => x.TableName.ToLower() == "kre_productcategory").FirstOrDefault();

    if (stagingTableConfig != null)
    {
        var listProductCategory = db1.KreProductCategory.Where(x => x.Id > stagingTableConfig.LastataIndex).ToList();

        if (listProductCategory.Count > 0)
        {   
            long lastIndex = listProductCategory.Select(x => x.Id).Max();
            stagingTableConfig.LastataIndex = lastIndex;

            List<T1Item> listT1Items = new List<T1Item>();

            foreach (var pc in listProductCategory)
            {
                T1Item t1Item = new T1Item()
                            {
                                TiKd = pc.Category,
                                TiNm = pc.Name,
                                FlagApproval = 0,
                                FlagCleansing = 0,
                                TiKet = pc.Description
                            };

                listT1Items.Add(t1Item);
            }

            db2.T1Item.AddRange(listT1Items);
            db2.SaveChanges();

            db1.KreTableFlagConfiguration.Update(stagingTableConfig);
            db2.SaveChanges();
        }
    }
}

我想知道是否有一种方法可以使用 ef core 插入它。也许还有另一种选择使用 ADO 网络插入到使用 PK 的表中。但如果我可以使用 EF Core,我更喜欢使用 EF Core。

编辑

modelBuilder.Entity<T1Item>(entity =>
            {
                entity.HasNoKey();

                entity.ToTable("T1_ITEM");

                entity.Property(e => e.FlagApproval)
                    .HasColumnName("FLAG_APPROVAL")
                    .HasColumnType("numeric(5, 0)");

                entity.Property(e => e.FlagCleansing)
                    .HasColumnName("FLAG_CLEANSING")
                    .HasColumnType("numeric(5, 0)");

                entity.Property(e => e.ItPk)
                    .HasColumnName("IT_PK")
                    .HasColumnType("numeric(10, 0)");

                entity.Property(e => e.TiKd)
                    .HasColumnName("TI_KD")
                    .HasMaxLength(5)
                    .IsUnicode(false)
                    .IsFixedLength();

                entity.Property(e => e.TiKet)
                    .HasColumnName("TI_KET")
                    .HasMaxLength(255)
                    .IsUnicode(false);

                entity.Property(e => e.TiNm)
                    .HasColumnName("TI_NM")
                    .HasMaxLength(255)
                    .IsUnicode(false);
            });

标签: c#entity-frameworkasp.net-core

解决方案


您可以在您Keyless的模型上使用属性或HasNoKey在 ef 核心中使用流利的 api,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
    .Entity<BlogPostsCount>(
        eb =>
        {
            eb.HasNoKey();
            eb.Property(v => v.BlogName).HasColumnName("Name");
        });
}

或用于使用属性:

[Keyless]
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}

但是,它们与常规实体类型的不同之处在于:

1-不能定义一个键。

2-永远不会跟踪 DbContext 中的更改,因此永远不会在数据库中插入、更新或删除。

3-从未按照惯例被发现。仅支持导航映射功能的子集,具体而言:它们可能永远不会充当关系的主要端。

4-他们可能没有到拥有实体的导航 他们只能包含指向常规实体的参考导航属性。

5-实体不能包含无键实体类型的导航属性。

6-可以映射到定义查询。定义查询是在模型中声明的查询,它充当无键实体类型的数据源。


推荐阅读