实体框架,code首先,更新"一对多"具有独立的关联关系 [英] Entity Framework, Code First, Update "one to many" relationship with independent associations

查看:114
本文介绍了实体框架,code首先,更新"一对多"具有独立的关联关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了太多的时间来找到解决下面描述的场景。我应该是看似简单的事情被证明是相当困难的。现在的问题是:

使用实体框架4.1(code第一种方法)和独立协会我怎么了超然的情景不同的最终分配给现有的多对一的关系(Asp.Net在我的情况)

模型:

我认识到,使用ForeignKey的关系,而不是独立的协会将是一个选择,但它是我的preference到没有一个ForeignKey的实施我的波苏斯。

一个客户有一个或多个目标:

 公共类客户:人
{
    公共弦数{搞定;组; }
    公共字符串NameContactPerson {搞定;组; }
    私人的ICollection<目标> _targets;    //独立协会
    公共虚拟的ICollection<目标>目标
    {
        {返回_targets? (_targets =新的集合<目标>()); }
        集合{_targets =价值; }
    }
}

一个目标有一个客户:

 公共类对象:EntityBase
{
    公共字符串名称{;组; }
    公共字符串描述{搞定;组; }
    公共字符串注意{搞定;组; }
    公共虚拟地址地址{搞定;组; }
    公共虚拟客户客户{搞定;组; }
}

客户从一个Person类派生的:

 公共类人:EntityBase
{
    公共字符串称谓{搞定;组; }
    公共字符串名称{搞定;组; }
    公共字符串名字{获得;组; }
    公共字符串名字{获得;设置; }
    公共字符串Telephone1 {搞定;组; }
    公共字符串Telephone2 {搞定;组; }
    公共字符串电子邮件{获得;组; }    公共虚拟地址地址{搞定;组; }
}

EntityBase类提供了一些常用的属性:

 公共抽象类EntityBase:INotifyPropertyChanged的
{
    公共EntityBase()
    {
        CREATEDATE = DateTime.Now;
        CHANGEDATE = CREATEDATE;
        CREATEUSER = HttpContext.Current.User.Identity.Name;
        ChangeUser = CREATEUSER;
        的PropertyChanged + = EntityBase_PropertyChanged;
    }    公共无效EntityBase_PropertyChanged(对象发件人,PropertyChangedEventArgs E)
    {
        如果(同上!=新的GUID())
        {
            CHANGEDATE = DateTime.Now;
            ChangeUser = HttpContext.Current.User.Identity.Name;
        }
    }    受保护的虚拟无效OnPropertyChanged(PropertyChangedEventArgs E)
    {
        PropertyChangedEventHandler处理器=的PropertyChanged;
        如果(!=处理空值)处理器(这一点,E);
    }    公共事件PropertyChangedEventHandler的PropertyChanged;    公众的Guid标识{搞定;组; }
    公众的DateTime CREATEDATE {搞定;组; }
    公众的DateTime? CHANGEDATE {搞定;组; }
    公共字符串CREATEUSER {搞定;组; }
    公共字符串ChangeUser {搞定;组; }
}

上下文:

 公共类TgrDbContext:的DbContext
{
    公共DbSet<&人GT;人{搞定;组; }
    公共DbSet<地址>地址{搞定;组; }
    公共DbSet<客户>客户{搞定;组; }
    公共DbSet<目标>目标{搞定;组; }
    公共DbSet<&的ReportRequest GT; ReportRequests {搞定;组; }    //如果OnModelCreating变得大,用型号配置类
    //(从EntityTypeConfiguration派生),而不是
    保护覆盖无效OnModelCreating(DbModelBuilder模型构建器)
    {
        modelBuilder.Entity<&人GT;()HasOptional(E => e.Address)。
        modelBuilder.Entity<客户方式>()的hasMany(C => c.Targets).WithRequired(T => t.Customer);
    }    公共静态的ObjectContext TgrObjectContext(TgrDbContext tgrDbContext)
    {
        返回((IObjectContextAdapter)tgrDbContext).ObjectContext;
    }
}


解决方案

我等着@马丁的答案,因为有这个问题更多的解决方案。这里是另外一个(至少它ObjectContext的API的工作,所以应该用的DbContext API以及工作):

  //现有客户
VAR的客户=新客户(){ID =客户ID};
//另一个现有客户
VAR的customer2 =新客户(){ID = customerId2};VAR的目标=新目标{ID = oldTargetId};
//使目标与老客户之间的连接
target.Customer =客户;//附加的目标与老客户
context.Targets.Attach(目标);
//连接第二个客户
context.Customers.Attach(customer2表);
//设置客户附在物体上一个新的值(它会删除旧的关系,并添加新的)
target.Customer =的customer2;//改变目标的状态,以修改
context.Entry(目标).STATE = EntityState.Modified;
context.SaveChanges();

这里的问题是内部EF内部状态模​​型和状态验证。在强制性的关系(在许多侧)不变或修改国家实体不能有独立的协会加入状态时,有在已删除状态,没有其他。修改状态的关联根本不允许的。

It took me way too long to find a solution to the scenario described below. What should seemingly be a simple affair proved to be rather difficult. The question is:

Using Entity Framework 4.1 (Code First approach) and "Independent associations" how do I assign a different end to an existing "many to one" relationship in a "detached" scenario ( Asp.Net in my case).

The model:

I realize that using ForeignKey relationships instead of Independent Associations would have been an option, but it was my preference to not have a ForeignKey implementation in my Pocos.

A Customer has one or more Targets:

    public class Customer:Person
{
    public string Number { get; set; }
    public string NameContactPerson { get; set; }
    private ICollection<Target> _targets;

    // Independent Association
    public virtual ICollection<Target> Targets
    {
        get { return _targets ?? (_targets = new Collection<Target>()); }
        set { _targets = value; }
    }
}

A Target has one Customer:

    public class Target:EntityBase
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string Note { get; set; }
    public virtual Address Address { get; set; }
    public virtual Customer Customer { get; set; }
}

Customer derives from a Person class:

    public class Person:EntityBase
{        
    public string Salutation { get; set; }
    public string Title { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set  ; }        
    public string Telephone1 { get; set; }
    public string Telephone2 { get; set; }
    public string Email { get; set; }        

    public virtual Address Address { get; set; }
}

EntityBase class provides some common properties:

    public abstract class EntityBase : INotifyPropertyChanged
{
    public EntityBase()
    {
        CreateDate = DateTime.Now;
        ChangeDate = CreateDate;
        CreateUser = HttpContext.Current.User.Identity.Name;
        ChangeUser = CreateUser;
        PropertyChanged += EntityBase_PropertyChanged;
    }

    public void EntityBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (Id != new Guid())
        {
            ChangeDate = DateTime.Now;
            ChangeUser = HttpContext.Current.User.Identity.Name;
        }
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, e);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public Guid Id { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime? ChangeDate { get; set; }
    public string CreateUser { get; set; }
    public string ChangeUser { get; set; }
}

The Context:

    public class TgrDbContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
    public DbSet<Address> Addresses { get; set; }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Target> Targets { get; set; }
    public DbSet<ReportRequest> ReportRequests { get; set; }

    // If OnModelCreating becomes to big, use "Model Configuration Classes"
    //(derived from EntityTypeConfiguration) instead
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().HasOptional(e => e.Address);            
        modelBuilder.Entity<Customer>().HasMany(c => c.Targets).WithRequired(t => t.Customer);            
    }

    public static ObjectContext TgrObjectContext(TgrDbContext tgrDbContext)
    {           
        return ((IObjectContextAdapter)tgrDbContext).ObjectContext;
    }
}

解决方案

I waited for @Martin answer because there are more solutions for this problem. Here is another one (at least it works with ObjectContext API so it should work with DbContext API as well):

// Existing customer
var customer = new Customer() { Id = customerId };
// Another existing customer
var customer2 = new Customer() { Id = customerId2 };

var target = new Target { ID = oldTargetId };
// Make connection between target and old customer
target.Customer = customer;

// Attach target with old customer
context.Targets.Attach(target);
// Attach second customer
context.Customers.Attach(customer2);
// Set customer to a new value on attached object (it will delete old relation and add new one)
target.Customer = customer2;

// Change target's state to Modified
context.Entry(target).State = EntityState.Modified;
context.SaveChanges();

The problem here is internal state model and state validations inside EF. Entity in unchanged or modified state with mandatory relation (on many side) cannot have independent association in added state when there is no other in deleted state. Modified state for association is not allowed at all.

这篇关于实体框架,code首先,更新&QUOT;一对多&QUOT;具有独立的关联关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆