在保存为大写之前强制执行

时间:2016-08-02 06:37:45

标签: c# entity-framework

我在db表中有三列,如下所示: enter image description here

当我添加新行时,它应该以大写形式将值存储在列fieldname上。我怎么能这样做?

4 个答案:

答案 0 :(得分:5)

由于您使用实体框架标记了问题,我假设您要在数据层或接近数据库中执行此操作。有很多方法可以做到这一点。

您可以在上下文中覆盖SaveChanges()这会将逻辑移离模型,但仍可确保保存正确的值。此外,如果您想在多个实体上使用它,您可以使用界面。当它是interface时,您可以为几个实体执行此操作而不需要任何重复代码,只要它是相同的属性即可。否则你需要一个属性和反射。可重用性非常高,但它会为您的SaveChanges()增加一些开销。

public class CustomerEntity()
{
    public string Name {get;set;}
}

public MyCustomContext : DbContext
{    
    // Other stuff...

    public override int SaveChanges()
    {
        foreach (var entry in ChangeTracker.Entries<CustomerEntity>())
        {
            if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
            {
                // Possibly check for null or if it's changed at all.
                entry.Entity.Name = entry.Entity.Name.ToUpper();
            }
        }
        return base.SaveChanges();
    }
}

使用界面:

public interface INameIsAlwaysUpperCase
{
    string Name {get;set;}
}

public MyCustomContext : DbContext
{    
    // Other stuff...

    public override int SaveChanges()
    {
        foreach (var entry in ChangeTracker.Entries<INameIsAlwaysUpperCase>())
        {
            if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
            {
                // Possibly check for null or if it's changed at all.
                entry.Entity.Name = entry.Entity.Name.ToUpper();
            }
        }
        return base.SaveChanges();
    }
}

您可以添加自定义验证。如果未正确保存,则会抛出异常。这样您就可以将责任转移给模型的消费者。但是,根据您的方案,您可能不想抛出异常。这是我的最爱,因为它迫使消费者以正确的方式来做这件事。根据评论,为什么抛出你可以默默地转换它?是的,这是一个有效的问题。对我来说,它是强迫数据层的消费者正确使用它,而不是让daya层决定数据的用途。当业务层要求数据层保存一件事时,我个人不喜欢它,然后数据层保存了另一件事。如果小写不是有效选项,则不应保存。我不认为它与使用[Required]更加不同。但它真的是关于背景以及在你的特定情况下有效的方法。

public class CustomerEntity() : IValidatableObject
{
    public string Name {get;set;}

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // Possibly check for null here as well...
        if (this.Name.ToUpper() != this.Name)
        {
            yield return new ValidationResult("You need to save as upper!"); 
        }
    }
}

使用管理此功能的属性。这可能是最简单的解决方案,即使我希望保持我的实体“干净”。绝对是需要最少努力的解决方案。但是,可重用性很低,如果您在整个应用程序中使用自己的权限并希望将值设置为小写,直到实际保存为止,该怎么办?那是不可能的。但是,再次,我认为这取决于您的具体情况。如果您希望在保存它之前将值设置为大写 ,这可能是最好的解决方案!

public class CustomerEntity()
{
    string _name;
    public string Name 
    {
        get { return _name; }
        set { _name = value.ToUpper(); } // Check for null ?
    }
}

保存时执行此操作。这会将逻辑移至您保存实体时。这可能是最不可取的选择,因为可重用性不存在。 Update()会发生什么?但是,OP明确指出“当我添加时,因此它可能仅在添加新实体时适用。在这种情况下,它很可能是最受欢迎的选择,因为它允许更新具有小写。但它必须依赖于用例。

public void AddCustomer(string name)
{
    var customer = new CustomerEntity
    {
        Name = name.ToUpper()
    };
    _context.Customers.Add(customer);
}

答案 1 :(得分:1)

只需使用属性。如果您的模型如下:

public class MyModel
{
    public int Id { get; set; }
    public string Description { get; set; }
    public string LanguageCode { get; set; }
    public string FiledName { get; set; }   
}

然后,将其更改为:

public class MyModel
{
    private string fieldName;

    public int Id { get; set; }
    public string Description { get; set; }
    public string LanguageCode { get; set; }
    public string FiledName 
    { 
        get { return filedName; }
        set
        {
            if(!string.IsNullOrEmpty(value))
                fieldName = value.ToUpper();
            else
                fieldName = value;              
        }
    }   
}

答案 2 :(得分:0)

尝试一下。

public string FiledName 
{ 
    get { return filedName; }
    set
    {
          filedName = !string.IsNullOrEmpty( value ) ? value.ToUpper() : value;           
    }
}   

答案 3 :(得分:0)

也可以使用自定义属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Standardized : Attribute
{}

然后在你的模型中装饰属性:

public class MyModel
{
    public string Id{ get; set; }

    [Required]
    [Standardized]
    public string Description { get; set; }
}

取自@smoksnes 接受的答案,在您的 DbContext 类中,覆盖 SaveChanges(), SaveChangesAsync() (EF Core 5.x) 并使用反射添加私有方法以获取装饰属性并应用转换,例如这:

public override int SaveChanges()
{
    StandardizeBeforeSaving();
    return base.SaveChanges();
}

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
    StandardizeBeforeSaving();
    return await base.SaveChangesAsync(cancellationToken);
}

private void StandardizeBeforeSaving()
{
    foreach (var entry in ChangeTracker.Entries())
    {
        if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
        {
            var properties = entry.Entity
                .GetType()
                .GetProperties()
                .Where(prop => Attribute.IsDefined(prop, typeof(Standardized)) && prop.PropertyType == typeof(string));

            foreach (var property in properties)
            {
                var value = entry.CurrentValues[property.Name]?.ToString() ?? string.Empty;
                entry.CurrentValues[property.Name] = value.Standardize();
            }
        }
    }
}

请注意,反射可能比已接受的答案中提供的其他技术慢。但对于大多数情况(即用户更新或创建几个属性不多的实体)应该没问题。