简体   繁体   English

Entity Framework Core主键中的引导字符串

[英]Guid string in primary key in Entity Framework Core

I have a problem regarding temporary values in primary keys in EF Core (2.1.4). 我对EF Core(2.1.4)中的主键中的临时值有问题。 The value is too long to fit in the database and validation using the DataAnnotations.Validator fails. 该值太长,无法放入数据库中,无法使用DataAnnotations.Validator进行验证。
If I disable the validator dbcontext.SaveChanges works and handle the value in the correct way. 如果禁用验证器, dbcontext.SaveChanges以正确的方式工作并处理该值。

I have an example table (SQL Server) with this definition: 我有一个具有此定义的示例表(SQL Server):

TestTable
Key1 numeric (18,0)
Key2 char (1) Default value: A

Key1 and Key2 are defined as primary key on the table. Key1Key2被定义为表上的主键。 Key2 has a default value of A. Key2的默认值为A。

This table is reverse engineered in EF Core to this POCO: 该表在EF Core中对此POCO进行了反向工程:

public partial class TestTable
{
    [Column(TypeName = "numeric(18, 0)")]
    public decimal Key1 { get; set; }
    [StringLength(1)]
    public string Key2 { get; set; }
}

Note that we are using data annotations on the POCO classes. 请注意,我们在POCO类上使用了数据注释。

The model generated looks like this: 生成的模型如下所示:

modelBuilder.Entity<TestTable>(entity =>
{
    entity.HasKey(e => new { e.Key1, e.Key2 });
    entity.Property(e => e.Key2)
        .IsUnicode(false)
        .HasDefaultValueSql("('A')");
});

I then add a new item to the dbcontext . 然后,我向dbcontext添加一个新项。

var testTbl = new TestTable { Key1 = 90};
db.TestTable.Add(testTbl);
db.Validate();
db.SaveChanges();

I don't specify Key2 as I want to use the default value from the database. 我没有指定Key2因为我想使用数据库中的默认值。

Before I call Context.SaveChanges() on the dbcontext I would like to validate the entities in the dbcontext. 在对dbcontext调用Context.SaveChanges()之前,我想验证dbcontext中的实体。 This best way I have found for that until now is: 到目前为止,我发现的最佳方法是:

Public void Validate()
{
    var entities = ChangeTracker.Entries()
    .Where(e => e.State == EntityState.Added || 
    e.State == EntityState.Modified)
    .Select(e => e.Entity)
    .ToList();

    foreach (var entity in entities)
    {
        var vContxt = new ValidationContext(entity);
        List<ValidationResult> validaRes = new List<ValidationResult>();

        if (!Validator.TryValidateObject(entity, validationContext, 
            validationResults, true))
        {
            //Handle validation errors.
        }
    }
}

My problem is that when I add the TestTable object to the dbcontext, Key2 string property automatically get assigned a guid value. 我的问题是,当我将TestTable对象添加到dbcontext时, Key2字符串属性会自动获得一个guid值。 When Validate is called it fails because Key2 is not supposed to have a string value longer than 1 character. 调用Validate时失败,因为Key2的字符串值不应超过1个字符。

If Key2 is not part of the primary key and I remove it from the HasKey method like this: 如果Key2不是主键的一部分,我将其从HasKey方法中删除,如下所示:

entity.HasKey(e => new { e.Key1 });

Then Key2 don't get a guid value assigned and the validation works. 然后Key2不会获得分配的guid值,并且验证有效。

Does someone know if there is a way to tell EF Core to not add a guid value to a string value that are part of a key and don't have a value specified? 有人知道是否有一种方法可以告诉EF Core不将guid值添加到键的一部分且没有指定值的字符串值中吗? Or is there a way to tell EF Core to obey the data annotation rules defined on the POCO object when assigning a temporary value? 还是有一种方法可以让EF Core在分配临时值时遵守POCO对象上定义的数据注释规则?

A composite primary key can only be defined by the fluent api. 复合主键只能由流利的api定义。
https://docs.microsoft.com/en-us/ef/core/modeling/keys https://docs.microsoft.com/en-us/ef/core/modeling/keys

Composite keys can only be configured using the Fluent API - conventions will never setup a composite key and you can not use Data Annotations to configure one. 只能使用Fluent API配置组合键-约定永远不会设置组合键,并且您不能使用数据注释来配置组合键。

However, you can even use data annotation. 但是,您甚至可以使用数据注释。
You can use the DatabaseGenerated attribute. 您可以使用DatabaseGenerated属性。
https://docs.microsoft.com/en-us/ef/core/modeling/generated-properties https://docs.microsoft.com/en-us/ef/core/modeling/generated-properties

public partial class TwoKeysTable
{
    public decimal Key1 { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public string Key2 { get; set; }

    public string Test { get; set; }
}

If you want to use fluent api: 如果您想使用流利的api:

entity.Property(e => e.Key2)
         .HasMaxLength(1)
         .HasDefaultValueSql("('A')")
         .ValueGeneratedOnAdd(); // add this 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM