实体框架验证上下文 - null test

时间:2015-06-19 19:45:12

标签: c# entity-framework

我正在处理PC配置程序应用程序,我在验证时遇到问题。应用点是检查主板上的插座是否与CPU等插座相同。

我在Visual Studio 2013中使用脚手架创建了代码第一个数据库。

public class Configuration : IValidatableObject
{
    [Key]
    public int ConfigurationID { get; set; }

    [Required]
    [StringLength(50, MinimumLength = 3)]
    [DisplayName("Configuration name")]
    public string ConfigName { get; set; }

    [ForeignKey("mb_id")]
    public MotherBoard MotherBoard { get; set; }

    [Column("mb_id", TypeName = "int")]
    public Nullable<int> mb_id { get; set; }

    [ForeignKey("cpu_id")]
    public CPU CPU { get; set; }

    [Column("cpu_id", TypeName = "int")]
    public Nullable<int> cpu_id { get; set; }
}

这是我正在使用的配置模型的一部分(其余部分看起来非常相似 - 只是其他组件)

我只是将这个模型搭建到控制器中。

这是验证的开始,似乎问题就在这里(至少VS说的是这样)。

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    if (MotherBoard == null) { throw new ArgumentNullException("Motherboard"); }
    if (CPU == null) { throw new ArgumentNullException("CPU"); }
    if (GPU == null) { throw new ArgumentNullException("GPU"); }
    if (HDD == null) { throw new ArgumentNullException("HDD"); }
    if (RAM == null) { throw new ArgumentNullException("RAM"); }
    if (Power == null) { throw new ArgumentNullException("Power"); }
    if (Case == null) { throw new ArgumentNullException("Case"); }

    if (MotherBoard.CPU.ToUpper().Trim() != CPU.Socket.ToUpper().Trim())
    {
            yield return new ValidationResult("CPU socket does not match.", new[] { "cpu_id" });
    }
}

当我在没有验证的情况下创建PC配置时,它会正常进入数据库。但是,当我尝试此验证时,它表示CPU(在null测试中)为null并抛出null异常。 Screenshot from VS.

它永远不会在主板上抛出,但总是在下一个项目上(第二项)。

1 个答案:

答案 0 :(得分:1)

CPU似乎被实体框架视为navigation property。没有更多信息,这表明您需要:

  1. using System.Data.Entity在任何单位选择模型
  2. 在枚举来自数据库的查询之前
  3. .Include(c => c.CPU)
  4. 如果它真的是navigation property,则可能是lazily loaded,如实体框架材料中所述。

    这意味着即使值似乎存在于数据库中,实际的集合 - 或者在您的情况下,引用 - 在内存中将为null。所以我们告诉实体框架&#34;包括&#34;我们取的那些项目:

    var configuration = db.ConfigurationsOrSomething
        .Include(c => c.CPU)
        .Where(c => c.DeletedOrWhatever == false)
        .ToList();
    
    var cpu = configuration.CPU;
    
    if(cpu == null)
        Debug.WriteLine("Something else is the problem. :(");
    

    您确实说过您已经看到了数据库中的值。我们无法看到您用于从数据库中选择实体的代码 - 或其他任何内容,如果还有其他内容。我们可以看到CPU是您定义和引用的另一种类型。如果你需要了解更多关于它的信息,你的模型看起来像EF Code First / Table-per-Type

    注意:我已经重新阅读了您的评论。当有人问你是否进入数据库时​​,你同意它是正常创建的#34;没有验证。

    我现在正在考虑您的整个设置是一个简单的验证失败。如果验证说CPU为空......则CPU为空。

    那么:您用于创建Configuration实体的新实例的代码在哪里?你只是没有为CPU分配值吗?