EntityFramework在创建dbcontext时删除了我的记录。

3
在一个.NET Core项目中,我有以下模型:
public class WrapperContext : DbContext
{
    public DbSet<WrappedFunction> Functions { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder builder)
    {
        builder.UseSqlite("Data Source=functions.db");
    }
}

public class WrappedFunction
{
    [Key]
    public int FunctionId { get; set; }
    public String FunctionName { get; set; }
    public String AssemblyPath { get; set; }
    public String FactoryName { get; set; }
}

你可以看到这是一个Sqlite数据库。

我已经添加了初始迁移并更新了数据库。在运行我的测试应用程序之前,我已经向Functions表中添加了一条记录。我可以使用SqliteManager打开DB来查看记录是否存在。

然后,我尝试使用以下函数访问数据库:

    static MUinfo getInfoFor(String command)
    {
        UFInfo rv = null;

        using (var ctx = new WrapperContext())  // <---- record disappears here
        {
            foreach (var fn in ctx.Functions)
            {
                if (fn.FunctionName.Equals(command))
                {
                    rv = new UFInfo()
                    {
                        AssemblyPath = fn.AssemblyPath,
                        FactoryName = fn.FactoryName,
                        CommandName = command
                    };
                }
            }
        }

        if (rv != null) return rv;
        return "No Info for " + command;
    }

然而,当我在调试器中逐步执行时,我发现foreach循环从未执行,因为数据库中没有记录。当我在执行foreach之前停止时,我可以使用SqliteManager验证我的单个记录已从数据库中删除。
因此,似乎DbContext对象以某种方式从数据库中删除了数据。这是为什么?我在这里做错了什么?我对EntityFramework相当新,所以我可能做了一些显而易见的事情,但对我来说并不明显。
这里有一个额外的信息。进行db访问的项目是库项目。在填充它并运行应用程序之前,我必须将DB复制到应用程序的构建目录中。我不知道这是否有影响。
编辑6/19/17(18:51):
好的。更多信息(感谢@StevePy)。 Nunit3似乎与EFCore冲突(尽管在还原时我没有收到任何错误),因此我无法为此创建单元测试。因此,我在上面的列表中插入了using(var ctx ...),并插入了几个虚拟记录。然后我退出了该使用块,当我进入遍历记录的使用块时,它们就在那里。
但是,然后我注释掉了虚拟插入并重新运行了我的测试。再次,两个记录都消失了。因此,EFCore存在一些非常奇怪的问题。
编辑6/20/17(15:30): 好吧,我仍然不确定发生了什么,但是EFCore和Microsoft.Data.Sqlite之间存在奇怪的交互作用。
我决定删除对EFCore的所有引用,只是在DB上使用SQL查询。我这样做时没有重新创建DB(因此我正在使用EFCore已经创建的DB)。当我创建一个新的SqliteConnection而不使用EFCore时,我注意到完全相同的行为。
绝望地,我从头开始删除了DB,并使用Microsoft.Data.Sqlite重新创建了它。这个DB显然没有任何EFCore信息。然后我用一些测试记录填充了DB并去使用它。不再消失记录。
显然,EFCore在第一次设置数据库时存在某些非常奇怪的问题。但我不知道那是什么。

@MarkC.,我遇到了错误:“DatabaseFacade”不包含“SetInitializer”的定义,也找不到扩展方法……。我尝试添加对System.Data.Entity的引用,但显然这与.NET Core不兼容。 - melston
好的,明白了。谢谢 - 这只是一次尝试。 - Mark C.
@CodingYoshi,是的。我正在SqliteManager中观察它,在代码步进时刷新,有一段时间数据存在,而在下一步则消失了。 - melston
你是怎么把数据放进去的?如果在上下文创建数据库之后插入一些数据,它是否仍会删除这些记录? - CodingYoshi
显然,我正在运行sqlite3可执行文件并读取插入记录的SQL文件。完成后,我可以在数据库中看到该记录。 - melston
显示剩余3条评论
1个回答

3
很可能发生的情况是您正在使用CodeFirst/w EF,但在测试新代码时采用了DB first方法。EF会跟踪数据库中的模式更改,我猜测您提前创建表格后它不知道模式是否经过审核,因此在上下文启动时删除并重新创建它。
解决方法应该是创建一个“存根”测试,使用您的EF模型一次填充一个测试记录。从那里开始,您应该有一个EF识别的表格,并接受该上下文。从那里,您可以在任何编辑器中创建测试记录。
SQLite在模式迁移方面有几个限制,您可能也要考虑。(请参阅:https://learn.microsoft.com/en-us/ef/core/providers/sqlite/limitations
您最好设置DB first,告诉EF如何映射到现有的SQLite模式,而不是尝试使用Code-First,因为对于该DB引擎来说迁移非常有限。

1
你怎么知道OP是采用DB优先的方法? - CodingYoshi
同意。这似乎更像是猜测而不是答案。 - Mark C.
@StevePy,我应该重写哪个方法才能进行这种数据填充? - melston
@melston:不要覆盖。如果您不熟悉NUnit和测试,请尝试添加一个简单的一次性方法:a)创建您的WrappedContext的实例,b)使用您想要的测试数据创建一个WrappedFunction,c)将其添加到上下文的Functions DbSet中,并c)调用上下文的SaveChanges。之后,删除存根方法并验证您的表是否已填充。编辑表内容以添加另一行,并运行现有代码以确定它是否仍在清除表。 - Steve Py
让我们在聊天中继续这个讨论 - melston
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接