【问题标题】:Entity Framework - per distinct string property only have one possible "true" value for other property实体框架 - 每个不同的字符串属性对于其他属性只有一个可能的“真”值
【发布时间】:2020-09-09 14:24:33
【问题描述】:

想象一下有一个像这个例子这样的实体:

public class Thing
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsActive { get; set; }
}

如何添加一个 constraint-ish 以便只有 ONE 具有特定名称的所有 Things 可以为 IsActive 使用 true

换句话说,我们可以有多个具有相同名称的Things,但在任何给定时间,只有一个IsActive 可以是true - 其他人需要有false 用于@987654329 @。所以如果我们要添加或更新一个,它需要检查新值是否为trueIsActive,它不会产生“冲突”。

这有可能吗?

【问题讨论】:

    标签: entity-framework unique distinct


    【解决方案1】:

    一种选择是采用更改实体状态的操作而不是公共设置器。例如,在大多数情况下,我的实体与 DbContext 和 Repository 类之类的东西一起驻留在域程序集中。 “事物”将驻留在唯一关联的容器实体下。

    public class Thing
    {
         public int Id { get; internal set;}
         public string Name { get; internal set; }
         public bool IsActive { get; internal set; }
    }
    
    public class Container
    {
         public int Id { get; internal set; }
         public virtual ICollection<Thing> Things { get; internal set; } = new List<Thing>();
    
         public void AddThing(string name, bool isActive = true)
         {
            var existingActiveThing = Things.SingleOrDefault(x => x.Name == name && x.IsActive);
            if(isActive && existingActiveThing != null)
                existingActiveThing.IsActive = false;
    
            var newThing = new Thing { Name = name, IsActive = isActive };
            Things.Add(newThing);
        }
    
        public void ActivateThing(int thingId)
        {
            var thing = Things.Single(x => x.Id == thingId);
            if(thing.IsActive)
                return; // Nothing to do.
            var existingActiveThing = Things.SingleOrDefault(x => x.Name == thing.Name && x.IsAcitve);
            if (existingActiveThing != null)
                existingActiveThing.IsActive = false;
    
            thing.IsActive = true;
        }
    
        // And so forth for instance Renaming a Thing or other allowed actions.
    }
    

    Container 可以是一个包含实体,或者这些操作可以封装在一个域级服务类中,该类使用 Things 的集合进行初始化,或者如果 Things 是一个顶级实体,则可以访问 DbContext。 setter 被标记为 Internal 以要求使用域级别的方法来改变状态,而不是通过 setter 进行任意更新。当您希望跨多个实体或多个字段强制验证以确保每个时间点的实体状态有效时,此技术可能很有用。 (即,将地址字段更新为一组要验证的值,而不是一次更新一个字段,您可以在其中更改 Country 等,使实体处于无法通过验证的无效值组合中)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-17
      • 2014-09-29
      • 2014-07-05
      • 1970-01-01
      相关资源
      最近更新 更多