0

我有一个作为 PK 的表,但是一旦我尝试运行应用程序,就会在DefaultEditionCreator.csCode中得到以下异常。

[Table("Test")]
public class Test: FullAuditedEntity<string>
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    new public int Id { get; set; }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [MaxLength(NVarcharLength14), DataType(DataType.Text)]
    public virtual string Code { get; set; }
}

声明的存储库:

private readonly IRepository<Article, string> _articleRepository;

例外:

System.InvalidOperationException:'int'类型的指定字段'k__BackingField'不能用于'string'类型的属性'Article.Id'。只能使用可从属性类型分配的类型的支持字段。

我在运行时遇到同样的错误,Update-Database并且Add-Migration.

更新 1

@aaron 非常感谢您的帮助。我已按照您的建议尝试了这些步骤,但在更新和删除记录时出现错误。

例外:

ERROR 2018-02-12 06:13:23,049 [30] Mvc.ExceptionHandling.AbpExceptionFilter - 更新条目时出错。有关详细信息,请参阅内部异常。Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:无法更新标识列“Id”。

public async Task UpdateTest()
{
   var entity = GetAll().Where(x => x.TestId == "One").FirstOrDefault();
   await UpdateAsync(entity);
}

public async Task DeleteTest()
{
   await DeleteAsync(x => x.TestId == "One"); 
}

public class Test : FullAuditedEntity
{
   // PK
   public string TestId { get; set; }

   // Unique constraint
   public int TestId2 { get; set; }
}

更新 2

我试图通过引用Disable SoftDelete for AbpUserRole来禁用 SoftDelete ,但它仍在执行 SoftDelete,而不是从 DB 中删除该行。请找到截图:

这里

public class TestAppService : MyProjectAppServiceBase, ITestAppService
{
    public Task DeleteTest()
    {
        using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
        {
            return _testRepository.DeleteTest();
        }
    }
}

MyDBContext.cs

protected override void CancelDeletionForSoftDelete(EntityEntry entry)
{
    if (IsSoftDeleteFilterEnabled)
    {
        base.CancelDeletionForSoftDelete(entry);
    }
}

该解决方案工作正常,但在运行测试用例创建Test实体时会出现以下异常。

SQLite 错误 19:'NOT NULL 约束失败:Test.Id'。

4

2 回答 2

1

您的意思是使用 varchar 类型作为主键吗?只需像这样声明实体类:

public class Article: Entity<string>
{
  //You should comment this line
  //[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  //new public int Id { get; set; }
}

然后你可以使用存储库:

private readonly IRepository<Article, string> _articleRepository;
于 2017-09-20T02:57:57.323 回答
1

例外是因为你继承了FullAuditedEntity<string>,它指定的Id是类型string,然后确实new将类型更改为int。这种隐藏会导致 EF 发生冲突。

您可以这样做:

  1. 有一个类型的自动增量Idint
  2. 有一个类型的主键列string
  3. 有一个唯一的约束列(根据相关论坛的要求)

代码:

public class Test: FullAuditedEntity
{
    // PK
    [MaxLength(NVarcharLength14), DataType(DataType.Text)]
    public virtual string Code { get; set; }

    // Unique constraint
    public int MyUniqueId { get; set; }
}

public class AbpProjectNameDbContext : AbpZeroDbContext<Tenant, Role, User, AbpProjectNameDbContext>
{
    /* Define a DbSet for each entity of the application */    
    public DbSet<Test> Tests { get; set; }

    public AbpProjectNameDbContext(DbContextOptions<AbpProjectNameDbContext> options) : base(options) {}

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Test>().Property(t => t.Id).ValueGeneratedOnAdd(); // Auto-increment
        modelBuilder.Entity<Test>().HasAlternateKey(t => t.Id);                // Auto-increment, closed-wont-fix: https://github.com/aspnet/EntityFrameworkCore/issues/7380
        modelBuilder.Entity<Test>().HasKey(t => t.Code);                       // PK
        modelBuilder.Entity<Test>().HasIndex(t => t.MyUniqueId).IsUnique();    // Unique constraint
    }
}

生成的迁移:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Tests",
        columns: table => new
        {
            Code = table.Column<string>(nullable: false),
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
            MyUniqueId = table.Column<int>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Tests", x => x.Code);
        });

    migrationBuilder.CreateIndex(
        name: "IX_Tests_MyUniqueId",
        table: "Tests",
        column: "MyUniqueId",
        unique: true);
}

用法:

public async Task MyMethod()
{
    await _repository.InsertAndGetIdAsync(new Test
    {
        Code = "One",
        MyUniqueId = 1
    });

    // Valid
    await _repository.InsertAndGetIdAsync(new Test
    {
        Code = "Two",
        MyUniqueId = 2
    });

    try
    {
        await _repository.InsertAndGetIdAsync(new Test
        {
            Code = "One", // PK conflict
            MyUniqueId = 3
        });
    }
    catch (Exception e)
    {
    }

    try
    {
        await _repository.InsertAndGetIdAsync(new Test
        {
            Code = "Three",
            MyUniqueId = 1 // Unique constraint conflict
        });
    }
    catch (Exception e)
    {
        throw;
    }

    return null;
}

为了完整起见,这个问题是一系列其他 Stack Overflow 问题中的第一个:

  1. 这个问题。(9 月 11 日)
  2. 调用 DeleteAsync 时发现不明确的匹配异常(9 月 11 日)
  3. 无法从具有标识列的表中删除记录(9 月 12 日)
  4. 如何在 ASP.NET 样板中制作复合唯一键?(9 月 13 日)
于 2018-02-04T02:42:40.553 回答