新手EF4.3& MVC4关系

时间:2012-03-02 16:40:03

标签: asp.net-mvc entity-framework-4

我有一个与另一张桌子有关系的课程。

public class MyClass
{
    [Key]
    public Guid Id {get; set; }

    public virtual OtherClass OtherClass { get; set; }
}

我将它连接到控制器并为CRUD创建视图 - 一切正常。

在DB中创建了一个OtherClass_OtherClassId列,但这不在模型中。

如何在控制器的Create方法中将引用放在此Id列中?

如何在不必每次都创建全新的OtherClass的情况下强制此关系为[必需]?

2 个答案:

答案 0 :(得分:3)

带有一些描述的带注释的类:

public class MyClass
{
    // [Key] - Don't actually need this attribute
    // EF Code First has a number of conventions.
    // Columns called "Id" are assumed to be the Key.
    public Guid Id {get; set; }

    // This reference creates an 'Independent Association'.  The Database
    // foreign key is created by convention and hidden away in the code.
    [Required]
    public virtual OtherClass OtherClass { get; set; }

    // This setup explicitly declares the foreign key property.
    // Again, by convention, EF assumes that "FooId" will be the key for
    // a reference to object "Foo"

    // This will still be required and a cascade-on-delete property
    // like above - an int? would make the association optional.
    public int OtherClass2Id { get; set; }

    // Leave the navigation property as this - no [Required]
    public virtual OtherClass2 { get; set; }
}

哪个更好? Independent associations或声明foriegn键?

独立关联使对象编程更接近。使用OOP,一个对象并不真正关心成员的Id。 ORM尝试覆盖这些关系,取得了不同程度的成功。

声明外键会将数据库问题放入您的模型中,但有些情况下这会使处理EF变得更加容易。

示例 - 当使用所需的独立关联更新对象时,EF将希望将整个对象图放在适当的位置。

public class MyClass
{
    public int Id {get; set; }
    public string Name { get; set; }
    [Required]  // Note the required.  An optional won't have issues below.
    public virtual OtherClass OtherClass { get; set; }
}

var c = db.MyClasses.Find(1);
c.Name = "Bruce Wayne";

// Validation error on c.OtherClass.
// EF expects required associations to be loaded.
db.SaveChanges();  

如果您要做的只是更新名称,您还必须从数据库中提取OtherClass,因为它是实体验证或attach a stubbed entity (assuming you know the id)所必需的。如果您明确声明了外键,那么您将不会遇到这种情况。

现在使用外键,您遇到了另一个问题:

public class MyClass
{
    public Guid Id {get; set; }
    public string Name { get; set; }

    public int OtherClassId { get; set }
    public virtual OtherClass OtherClass { get; set; }
}

var c = db.MyClasses.Find(1);

// Stepping through dubugger, here, c.OtherClassId = old id

c.OtherClass = somethingElse;

// c.OtherClassId = old id - Object and id not synced!

db.SaveChanges();               

// c.OtherClassId = new id, association persists correctly though.

总结 -

独立协会

  • 好:匹配OOP和POCO更好
  • 错误:即使您只更新一个或两个属性,通常也需要完整的对象图。更多EF头痛。

外键

  • 好:有时更容易使用 - 更少的EF头痛。
  • 错误:可能与其对象不同步
  • 错误:POCO中的数据库问题

答案 1 :(得分:0)

EF通常需要手持模型配置。这应该让你开始。但是,首先在EF Code First和DB上做一个好的教程将会非常有益。

以下有:

  • 使用多个OrderItems订购
  • 单个用户
  • 并通过保持标识OrderTypeId和实际的OrderType ref对象来生成单个OrderType。

    公共类订单 {     公共秩序()     {         OrderItems = new OrderItemCollection();     }

    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string OrderName { get; set; }
    
    public int UserId { get; set; }
    public virtual User OrderUser { get; set; }
    
    public virtual OrderItemCollection OrderItems { get; set; }
    public int? OrderTypeId { get; set; }
    public OrderType OrderType { get; set; }
    public override int GetHashCode() { return OrderID.GetHashCode();}
    

    } 公共类OrderConfiguration:EntityTypeConfiguration {     public OrderConfiguration()     {         this.ToTable( “命令”);         this.HasKey(p => p.OrderID);         this.Property(x => x.OrderID).HasColumnName(“ORDER_ID”);         this.Property(x => x.OrderName).HasMaxLength(200);         this.HasMany(x => x.OrderItems).WithOptional()。HasForeignKey(x => x.OrderID).WillCascadeOnDelete(true);

        this.HasRequired(u => u.OrderUser).WithMany().HasForeignKey(u => u.UserId);
        this.Property(x => x.OrderTypeId).HasColumnName("ORDER_TYPE_ID");
        this.HasOptional(u => u.OrderType).WithMany().HasForeignKey(u => u.OrderTypeId);
    }
    

    } 公共类OrderContext:DbContext {     protected override void OnModelCreating(DbModelBuilder modelBuilder)     {         modelBuilder.Configurations.Add(new OrderConfiguration());     } } “