Обновление модели приводит к удалению интерфейса из DbContext при использовании Effort с Entity Framework

В настоящее время я пытаюсь использовать Effort ( https://effort.codeplex.com/) с моим решением Entity Framework 6, чтобы разрешить модульное тестирование без подключения к базе данных (см. 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; }
    }
}

Проблема в том, если я обновлю .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 подавать каждый раз. Кроме того, удаляет [Key] от POCO CCS_DEPT_TBL файл.

Есть ли способ настроить мой проект Entity Framework, чтобы он не сдул интерфейс и перегруженные конструкторы каждый раз, когда я обновляю модель из базы данных? ТИА.

ОБНОВИТЬ:

Поскольку класс является частичным, я просто гарантирую, что интерфейс и перегруженные конструкторы помещаются в отдельный файл, который не генерируется автоматически.

ОБНОВЛЕНИЕ 2:

ОК, понял, просто добавил это в отдельный файл, взяв DEPTID из оригинала POCO файл, но он все еще помещает это DEPTID в сгенерированном файле, поэтому после обновления сборка прерывается, потому что есть два 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; }
    }
}

Итак, как я могу предотвратить его генерацию DEPTID в сгенерированном файле класса, так как он уже находится в вышеуказанном частичном файле класса?

2 ответа

Решение

Да, класс определяется как частичный класс. Создайте новый файл, который также объявляет тот же частичный класс, и добавьте туда дополнительные методы.

Что касается потери атрибута [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; }    
    }
}

Спасибо @ Роберт Макки! Вот что я в итоге сделал:

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 на самом деле является объектами с первой базой данных, но есть три других файла *.edmx, которые являются объектами с первым кодом в том же проекте, поэтому закомментировал это исключение в HRModel.Context.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.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, где для Effort необходим интерфейс IHRADDbContext:

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;
        }
    }
}
Другие вопросы по тегам