【问题标题】:Entity Framework 6.1.1 can't get new Entity to work with Unity of Work Factory and Repository patternEntity Framework 6.1.1 无法让新实体与 Unity of Work Factory 和 Repository 模式一起使用
【发布时间】:2017-01-21 06:46:55
【问题描述】:

我向我的 MVC 5 Web API 项目添加了一个新实体,但我无法让它与我现有的 SQL 数据库一起使用。我现有的代码使用工作单元工厂和存储库模式从数据库读取和写入,所以我知道代码有效。没有edmx文件,所以我相信代码最初是先用代码写的。以下是我目前采取的步骤。

步骤 1) 将新实体添加到我的实体文件夹 步骤 2) 更新 DbContext 文件 步骤 3) 更新 UnitOfWork.cs 文件 步骤 4) 使用脚本手动创建新的 SQL 表 第 5 步)将以下代码添加到我的 Web API 服务中

using (var uow = _unitOfWorkFactory.Create())
            {

//Code to create newentity object

uow.newEntityRepository.Insert(newentity);
await uow.SaveChangesAsync(); 
}

我没有收到错误消息。插入根本不会将记录添加到数据库中。

我已经使用 EntityTypeConfiguration 创建了一个实体表映射,并使用 OnModelCreating Override 调用它。

EntityTypeConfiguration

public class NewEntityMap : EntityTypeConfiguration<NewEntity>
    {
        public NewEntityMap() : base()
        {
            // Primary Key
            this.HasKey(t => t.Id);


            // Table & Column Mappings
            this.ToTable("NewEntity", "dbo");
            this.Property(t => t.Id).HasColumnName("Id");
            this.Property(t => t.Created).HasColumnName("Created");
            this.Property(t => t.OfferId).HasColumnName("OfferId");
            this.Property(t => t.MerchantId).HasColumnName("MerchantId");
            this.Property(t => t.ConsumerId).HasColumnName("ConsumerId");
            this.Property(t => t.SMSMessage).HasColumnName("SMSMessage");
            this.Property(t => t.SendSMS).HasColumnName("SendSMS");
            this.Property(t => t.EmailMessage).HasColumnName("EmailMessage");
            this.Property(t => t.SendEmail).HasColumnName("SendEmail");
            this.Property(t => t.Source).HasColumnName("Source");
            this.Property(t => t.FromSMSNumber).HasColumnName("FromSMSNumber");
        }
    }

OnModelCreating

modelBuilder.Configurations.Add(new newEntityMap()); 

我仍然无法在表格中更新记录。

有什么想法吗?提前致谢!

【问题讨论】:

标签: entity-framework


【解决方案1】:

EF 代码优先非常简单,所以应该可以。如果您不使用迁移,您实际上只需添加一个新模型类(与您现有的表定义匹配)并将 DbSet NewEntities 添加到您的 DbContext 类中,听起来就像您所做的那样。

尝试通过消除过程来追踪问题的几件事。

  1. 创建一个新的空控制台应用项目进行测试。
static void Main(string[] args)
{
    MainAsync().Wait();
    Console.ReadLine();
}

static async Task MainAsync()
{
    /* Here's where we're gonna start troubleshooting */
}
  1. 引用您的实体项目并尝试首先使用所有必要/必需的属性实例化实体类。
static void Main(string[] args)
{
    MainAsync().Wait();
    Console.ReadLine();
}

static async Task MainAsync()
{
    // Test instantiating the Entity
    var newEntity = new NewEntity() { propName: value };
}
  1. 运行项目并确保其正常工作。如果不是,则说明您的实体存在问题。否则,继续第 4 步。

  2. 在步骤 2 中的代码的基础上,添加对包含 DbContext 的项目的引用。现在尝试像这样直接使用 DbContext:

static void Main(string[] args)
{
    MainAsync().Wait();
    Console.ReadLine();
}

static async Task MainAsync()
{
    // Test instantiating the Entity
    var newEntity = new NewEntity() { propName: value };

    // Now, let's test the Entity with the DbContext directly
    using (var db = new DbContext())
    {
        db.NewEntities.Add(newEntity);
        await db.SaveChangesAsync();
    }
}
  1. 运行/调试上面的代码。如果失败,您应该从 EF 获得异常。否则,请继续执行第 6 步。
  2. 以步骤 4 中的代码为基础。添加对包含您的存储库的项目的引用。现在,尝试像这样直接使用存储库:
static void Main(string[] args)
{
    MainAsync().Wait();
    Console.ReadLine();
}

static async Task MainAsync()
{
    // Test instantiating the Entity
    var newEntity = new NewEntity() { propName: value };

    // Now, let's test the Entity with the DbContext directly
    using (var db = new DbContext())
    {
        //db.NewEntities.Add(newEntity);
        //await db.SaveChangesAsync();

        // Now, let's test the entity with the DbContext and the Repository
        // Adjust the lines below as needed if you're not using a generic repository and/or if your insert method is called something else
        var repository = new EntityRepository<NewEntity>(db);
        repository.Insert(newEntity);
        // Comment out the line below if your repository internally calls SaveChangesAsync() on the DbContext
        // If your Repository class doesn't have a SaveChangesAsync method, you'll need to add one to test it
        await repository.SaveChangesAsync();
    }
}
  1. 如果失败,您应该得到一个可以追踪的异常。否则,请继续执行第 8 步。
  2. 以第 6 步中的代码为基础,添加对包含工作单元工厂的项目的引用(如果尚未引用)。现在,尝试像这样直接使用 Unit of Work 工厂:
static void Main(string[] args)
{
    MainAsync().Wait();
    Console.ReadLine();
}

static async Task MainAsync()
{
    // Test instantiating the Entity
    var newEntity = new NewEntity() { propName: value };

    // Now, let's test the Entity with the DbContext directly
    //using (var db = new DbContext())
    //{
        //db.NewEntities.Add(newEntity);
        //await db.SaveChangesAsync();

        // Now, let's test the entity with the DbContext and the Repository
        // Adjust the lines below as needed if you're not using a generic repository and/or if your insert method is called something else
        //var repository = new EntityRepository<NewEntity>(db);
        repository.Insert(newEntity);
        // Comment out the line below if your repository internally calls SaveChangesAsync() on the DbContext
        //await repository.SaveChangesAsync();
    //}

    // Now, let's test the entity with the UnitOfWork
    var uow = new UnitOfWork();
    uow.NewEntityRepository.Insert(newEntity);
    await uow.SaveChangesAsync();
}
  1. 如果失败,您应该得到一个可以追踪的异常。否则,请继续执行第 10 步。
  2. 如果以上所有方法都在没有依赖注入的情况下工作,那么我说你的组件注册到你的 DI 容器有问题。您需要确保这些接口的真实实例(实现)为运行时绑定和注册。

在 EF 方面,确保您没有任何外键或虚拟导航属性指向未正确修饰或未正确填充的其他实体。此外,请确保您传递给定模型的所有必需属性。如果不通过测试项目运行它,您的应用可能会吞下某个地方发生的错误,而您只是看不到它,但是通过我上面概述的消除过程,您应该能够找到问题。

一旦发现问题,您可能需要重新考虑在实体框架之上使用工作单元和存储库模式,因为它们本质上结合了这两种模式。见this post

祝你好运。

【讨论】:

  • 这正在工作。谢谢你的帮助。我不必使用包管理器控制台发出任何迁移命令。我不必使用任何工具将表逆向工程为实体/模型。我真正需要做的就是确保我的实体设置正确。将 DbSet 条目添加到 DBContex 文件中,并确保我的对象将正确的值传递到数据库中。
【解决方案2】:

您是否使用 nuget 包管理器控制台生成脚本来更新数据库?

你:

a) 您的项目中有一个“迁移”文件夹吗? b) 在您的数据库中有一个“MigrationHistory”表吗? c) 您的代码中是否有“Database.SetInitializer”行?

这些将是您首先运行代码的指标。 DbContext 中的代码可能很有用。

【讨论】:

  • 我没有使用包管理器控制台生成脚本来更新数据库。我不确定是否需要这样做,因为我使用数据库脚本手动创建了新表。
  • 我的主 Web 项目中有一个 Migrations 文件夹。它包含一个 Configuration.cs 文件。我的数据库中有一个 dbo.MigrationsHistory 表,但其中没有记录。我还将这一行添加到我的 DbContext 文件中。公共 DbSet NewEntities { 获取;放; }
  • 我找到了这行代码。 public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { Database.SetInitializer&lt;ApplicationDbContext&gt;(null); }
【解决方案3】:

一些事情:

您确定 conn 字符串指向您期望的数据库吗?

您向 DbContext 添加了一个用于 NewEntity 的 DbSet?

repository.Insert 方法有什么作用?

uow 和存储库是否使用工厂中相同的 DbContext 实例?还是两者都获得了不同的上下文实例? (即 IoC 设置为不在同一会话中提供相同的实例,或者您已设置。)

【讨论】:

  • 是的,连接字符串是正确的。我在我的项目中使用与其他服务相同的代码。是的,我确实为 NewEntity 添加了 DbSet。是的,uow 和存储库正在使用相同的 DbContext 实例。 uow 和存储库使用所有相同的代码,所以我很确定这不是问题。我在想我可能必须使用包管理器控制台让实体框架创建数据库并更新架构,但我不确定。
  • 如果你直接在 repo 的 Insert 方法中调用 SaveChanges 会发生什么?它仍然什么都不做吗?有没有 .Commit() 你必须调用?
  • 没有错误,应用程序处理一切正常。 .Insert 调用此方法。 public void Insert(T item) { _context.Set&lt;T&gt;().Add(item); }SaveChangesAsync() 调用此方法public Task SaveChangesAsync() { return _context.SaveChangesAsync(); }
  • 你有一个 TransactionScope 上面没有调用 .Commit() 的所有代码吗?
  • 否则,我会运行 SQL Profiler 来查看您的 SQL 语句是否完全通过网络。
猜你喜欢
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
  • 2016-05-23
相关资源
最近更新 更多