将 Effort 与 Entity Framework 结合使用时,更新模型会导致接口从 DbContext 中删除
Update model causes interface to be removed from DbContext when using Effort with Entity Framework
目前,我正在尝试使用 Effort (https://effort.codeplex.com/) with my Entity Framework 6 solution to allow unit testing without requiring a database connection (see http://www.codeproject.com/Articles/460175/Two-strategies-for-testing-Entity-Framework-Effort)。在我的项目中一切正常,这是带有接口的 DbContext
和 Effort 所需的重载构造函数:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext, IHRADDbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
问题是,如果我通过选择 "Update model from database..." 更新 .edmx
文件,那么它将重新生成上下文文件为:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
public partial class HRADDbContext : DbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
所以我每次都得回去手动更新上面的Context.cs
文件。此外,从 POCO CCS_DEPT_TBL
文件中删除 [Key]
。
有没有什么方法可以设置我的 Entity Framework 项目,以便它不会在我每次从数据库更新模型时破坏接口和重载构造函数? TIA.
更新:
由于 class 是部分的,我只是确保将接口和重载的构造函数放在一个单独的文件中,该文件不会自动生成。
更新 2:
好的,知道了,只是将其添加为一个单独的文件,将 DEPTID
从原始 POCO
文件中取出,但它仍然将 DEPTID
放入生成的文件中,因此在更新后构建中断,因为在同一个 class:
中有两个 DEPTID
值
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class CCS_DEPT_TBL
{
[Key]
public string DEPTID { get; set; }
}
}
那么,如何防止它在生成的 class 文件中生成 DEPTID
,因为它已经在上面的部分 class 文件中了?
是的,class 被定义为部分 class。创建一个新文件,该文件也声明相同的部分 class 并在其中添加其他方法。
至于 [Key] 属性丢失,您可以尝试使用 MetadataType 属性并将所有元数据放在那里。
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
... Your additional constructors and methods here ...
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
谢谢@Robert McKee!这是我最后做的:
CCS_DEPT_TBL_Key.cs:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
CCS_DEPT_TBL.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
public partial class CCS_DEPT_TBL
{
// This table in SQL Server does not have a primary key, it just has an index
public string DEPTID { get; set; }
public string DESCR { get; set; }
public System.DateTime EFFDT { get; set; }
public string EFF_STATUS { get; set; }
public Nullable<System.DateTime> LASTUPDDTTM { get; set; }
}
}
HRModel.Context.cs: HRADDbContext其实是database-first entities,但是同一个项目中还有另外三个*.edmx文件是code-first entities,所以在[=26=中注释掉这个异常] 因为它不适用。最好将数据库优先实体分离到一个单独的项目中,这样就不会在数据库模型更新时生成此异常。
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext
{
public HRADDbContext()
: base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
HRADDbContext.cs,其中 IHRADDbContext 接口对于 Effort 是必需的:
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
/// <summary>
/// Added interface here so that it does not get removed when updating
/// model from the database on code generation.
/// </summary>
partial class HRADDbContext : IHRADDbContext
{
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
}
}
目前,我正在尝试使用 Effort (https://effort.codeplex.com/) with my Entity Framework 6 solution to allow unit testing without requiring a database connection (see http://www.codeproject.com/Articles/460175/Two-strategies-for-testing-Entity-Framework-Effort)。在我的项目中一切正常,这是带有接口的 DbContext
和 Effort 所需的重载构造函数:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext, IHRADDbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
问题是,如果我通过选择 "Update model from database..." 更新 .edmx
文件,那么它将重新生成上下文文件为:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Common;
using System.Data.Entity;
public partial class HRADDbContext : DbContext
{
public HRADDbContext() : base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
所以我每次都得回去手动更新上面的Context.cs
文件。此外,从 POCO CCS_DEPT_TBL
文件中删除 [Key]
。
有没有什么方法可以设置我的 Entity Framework 项目,以便它不会在我每次从数据库更新模型时破坏接口和重载构造函数? TIA.
更新:
由于 class 是部分的,我只是确保将接口和重载的构造函数放在一个单独的文件中,该文件不会自动生成。
更新 2:
好的,知道了,只是将其添加为一个单独的文件,将 DEPTID
从原始 POCO
文件中取出,但它仍然将 DEPTID
放入生成的文件中,因此在更新后构建中断,因为在同一个 class:
DEPTID
值
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class CCS_DEPT_TBL
{
[Key]
public string DEPTID { get; set; }
}
}
那么,如何防止它在生成的 class 文件中生成 DEPTID
,因为它已经在上面的部分 class 文件中了?
是的,class 被定义为部分 class。创建一个新文件,该文件也声明相同的部分 class 并在其中添加其他方法。
至于 [Key] 属性丢失,您可以尝试使用 MetadataType 属性并将所有元数据放在那里。
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
... Your additional constructors and methods here ...
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
谢谢@Robert McKee!这是我最后做的:
CCS_DEPT_TBL_Key.cs:
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[MetadataType(typeof(CCS_DEPT_TBL_Meta))]
public partial class CCS_DEPT_TBL
{
}
public class CCS_DEPT_TBL_Meta
{
[Key]
public string DEPTID { get; set; }
}
}
CCS_DEPT_TBL.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Collections.Generic;
public partial class CCS_DEPT_TBL
{
// This table in SQL Server does not have a primary key, it just has an index
public string DEPTID { get; set; }
public string DESCR { get; set; }
public System.DateTime EFFDT { get; set; }
public string EFF_STATUS { get; set; }
public Nullable<System.DateTime> LASTUPDDTTM { get; set; }
}
}
HRModel.Context.cs: HRADDbContext其实是database-first entities,但是同一个项目中还有另外三个*.edmx文件是code-first entities,所以在[=26=中注释掉这个异常] 因为它不适用。最好将数据库优先实体分离到一个单独的项目中,这样就不会在数据库模型更新时生成此异常。
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class HRADDbContext : DbContext
{
public HRADDbContext()
: base("name=HRADDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CCS_DEPT_TBL> CCS_DEPT_TBL { get; set; }
public virtual DbSet<CCS_HR_AD_SYNC> CCS_HR_AD_SYNC { get; set; }
}
}
HRADDbContext.cs,其中 IHRADDbContext 接口对于 Effort 是必需的:
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
namespace Cssd.IT.PortalIntegration.DataAccess.HR.Dao
{
/// <summary>
/// Added interface here so that it does not get removed when updating
/// model from the database on code generation.
/// </summary>
partial class HRADDbContext : IHRADDbContext
{
public HRADDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}
public HRADDbContext(DbConnection connection)
: base(connection, true)
{
this.Configuration.LazyLoadingEnabled = false;
}
}
}