【问题标题】:must be non-nullable in order to use as parameter 'T'必须不可为空才能用作参数“T”
【发布时间】:2012-11-01 20:12:07
【问题描述】:

我正在尝试使用我自己的对象类型创建一个 Code First 类并收到此错误:

.MTObject' 必须是不可为空的值类型才能将其用作 泛型类型或方法中的参数“T” 'System.Data.Entity.ModelConfiguration.Configuration.StructuralTypeConfiguration<TStructuralType>.Property<T>(System.Linq.Expressions.Expression<System.Func<TStructuralType,T>>)'

有没有办法声明我的类属性来克服这个错误?

代码如下:

// Simple Example

public class MTObject
{
    public string Object { get; set; }

    public MTObject()
    {

    }
}

public class Person
{
    public decimal Id { get; set; }

    //public string Name { get; set; }

    public MTObject Name { get; set; }

    public Int32 Age { get; set; }
}

public class PersonConfiguration : EntityTypeConfiguration<Person>
{
    public PersonConfiguration() : base()
    {
        HasKey(p => p.Id);
        Property(p => p.Id).HasColumnName("ID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        Property(p => p.Name).HasColumnName("NAME").IsOptional();
        Property(p => p.Age).HasColumnName("AGE").IsOptional();
        ToTable("Person");
    }
}

public class PersonDataBase : DbContext
{
    public DbSet<Person> Persons { get; set; }

    public PersonDataBase(string connectionString) : base(connectionString)
    {
        Database.CreateIfNotExists();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new PersonConfiguration());
        base.OnModelCreating(modelBuilder);
    }
}

// End Simple EXample

【问题讨论】:

  • 这是 .net 吗?无论如何,请用语言标签标记问题(并可能删除不太相关的标签之一,如“编译器错误”)

标签: c# .net entity-framework code-first


【解决方案1】:

为了得到这行编译...

Property(p => p.Age).HasColumnName("AGE").IsOptional();

...您需要将Age 属性设为可为空:

public Nullable<Int32> Age { get; set; }

(或public int? Age { get; set; }

或者您不能将属性指定为可选属性,需要将其用作必需属性。

编辑

我上面的回答是错误的。这不是编译器错误的原因。但如果Age 属性应该是可选,则它必须仍然可以为空,即允许null 值。

编辑 2

在您的模型中,MTObject 是一种复杂类型(不是实体),因为按照惯例,EF 无法推断出主键属性。对于复杂类型,您可以将嵌套属性映射为:

Property(p => p.Name.Object).HasColumnName("NAME");

(假设您实际上想为Object 属性指定列名)使用IsOptional() 不是必需的,因为string 属性默认情况下是可选的。

【讨论】:

  • 另外,Name 是一个引用类型;它不直接映射到 SQL 类型,所以它应该是一个导航属性。然后它总是可选的。
  • 这真的不是问题所在。问题是数据库不知道MTObject 是什么。它需要是值类型或字符串...
  • @Tejs:是的,你是对的。我在上面的编辑 2 中假设的导航属性或复杂类型。
【解决方案2】:

只是为了帮助别人

在这种情况下只需更改

Property(p => p.Name).HasColumnName("NAME").IsOptional();

Property(p => p.Name.Object).HasColumnName("NAME").IsOptional();

【讨论】:

    【解决方案3】:

    “non-nullable”不是该错误消息的重要部分。重要的位是“必须是值类型”。 (“不可为空”只是“值类型”的修饰符)

    试试

    public struct MTObject
    {
        public string Object { get; set; }
    }
    
    public struct Person
    {
        public decimal Id { get; set; }
    
        //public string Name { get; set; }
    
        public MTObject Name { get; set; }
    
        public Int32 Age { get; set; }
    }
    

    (注意关键字struct而不是class

    【讨论】:

    • 你确定这是因为 Person 而不是因为 Name 属性? ;)
    • @MatíasFidemraizer:不,我不确定。重要的是传入的数据需要是值类型。
    • 仔细检查错误。关于MTObject。不能是引用类型的是映射到MTObject 类型属性的可选列。这是Name 属性不能是可选的。
    • @MatíasFidemraizer:所以我建议将 MTObject 设为值类型。
    • 糟糕,抱歉,我没有读到您将“MTObject”设为struct。顺便说一句,Person 仍然可以是class。对不起我的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    相关资源
    最近更新 更多