【发布时间】:2016-11-03 00:09:59
【问题描述】:
创建一个包含实体框架模型和对象上下文的类库。然后将新的控制台应用程序添加到解决方案中。在控制台应用程序中,引用具有您的模型的项目。
现在在控制台应用程序中输入:
static void Main(string[] args)
{
using (var context = new ExperimentalDbContext())
{
}
Console.ReadKey();
}
在构建时,您会收到一个错误报告:
类型“System.Data.Entity.DbContext”在一个程序集中定义,该程序集 没有被引用。您必须添加对程序集的引用 EntityFramework...yada yada yada...
现在,这几年我已经做了很多次了,但是每次遇到这个错误,我又一次无奈地在网上搜索了我当时忘记的解决方案。
解决此问题需要您在 ConsoleClient 项目中安装 EntityFramework NuGet 包。
所以,我的问题不在于修复是什么,而是为什么?因为它没有任何意义!
为了完整起见,我使用的是实体框架的 v6.1.3。但多年来,我在早期版本中也多次看到此错误。
更新
问题似乎只是当您使用using 代码块时,该代码块旨在在IDisposables 上调用Dispose。
要检验假设,请创建一个控制台应用程序,该应用程序在同一解决方案中引用 ClassLibrary1,在同一解决方案中引用 ClassLibrary2,代码如下:
using ClassLibrary1;
using System;
namespace TestHypothesis1
{
class Program
{
// Testing the hypothesis presented in this answer: http://stackoverflow.com/a/38130945/303685
// This seems to be the behavior with just (or may be even others I haven't tested for)
// IDisposable.
// anotherFoo instance is created just fine, but the moment I uncomment
// the using statement code, it shrieks.
static void Main(string[] args)
{
//using (var foo = new Foo())
//{
// foo.Gar = "Gar";
// Console.WriteLine(foo.Gar);
//}
var anotherFoo = new Foo() { Gar = "Another gar" };
Console.WriteLine(anotherFoo.Gar);
Console.ReadKey();
}
}
}
using ClassLibrary2;
using System;
namespace ClassLibrary1
{
public class Foo: Bar, IDisposable
{
public string Gar { get; set; }
public void Dispose()
{
throw new NotImplementedException();
}
}
}
namespace ClassLibrary2
{
public class Bar
{
public string Name { get; set; }
}
}
您会发现编译器抱怨缺少引用仅针对第一个 Foo 的实例化,而不是第二个实例。
奇怪的是,在第一个 EntityFramework 示例中,如果您从控制台应用程序中删除了对 EntityFramework.dll 的引用并将Main 中的代码更改为此,它仍然会抱怨缺少引用。
static void Main(string[] args)
{
var context = new ExperimentalDbContext();
Console.ReadKey();
context.Dispose();
}
此外,如果您注释掉对 context.Dispose() 的调用,即上面代码 sn-p 的最后一行,代码仍然可以正常工作,即使它抛出了 InvalidOperationException,但我猜这是由于在其迭代器完成其MoveNext 调用之前释放上下文的竞争条件。
static void Main(string[] args)
{
var context = new ExperimentalDbContext();
Console.ReadKey();
// context.Dispose();
}
所以,新的附加问题现在变成了:
using 语句的实现方式是什么导致编译器在链接引用时停在其轨道上?
原来的问题仍然存在。
又一次更新
现在看来,问题可能进一步归结为对IDisposable.Dispose 方法的调用,因此问题不在于using 语句的实现。 using 声明似乎是一个无辜的保证,即 Dispose 将被调用,而不是其他任何东西。
因此,在上面的Foo 示例中,如果您在最后插入对anotherFoo.Dispose 的调用,编译器就会再次开始报错。像这样:
using ClassLibrary1;
using System;
namespace TestHypothesis1
{
class Program
{
// Testing the hypothesis presented in this answer: http://stackoverflow.com/a/38130945/303685
// This seems to be the behavior with just (or may be even others I haven't tested for)
// IDisposable.
// anotherFoo instance is created just fine, but the moment I uncomment
// the using statement code, it shrieks.
// Final update:
// The trigger for the error seems to be the call to the Dispose method and not
// particularly the implementation of the using statement, which apparently, simply
// ensures that Dispose is called, as is also well-known and documented.
static void Main(string[] args)
{
//using (var foo = new Foo())
//{
// foo.Gar = "Gar";
// Console.WriteLine(foo.Gar);
//}
var anotherFoo = new Foo() { Gar = "Another gar" };
Console.WriteLine(anotherFoo.Gar);
anotherFoo.Dispose();
Console.ReadKey();
}
}
}
那么,最后一个问题,总结来说是这样的:
为什么对Dispose 的调用会阻止编译器链接程序集引用?
我认为我们现在正在取得进展。
【问题讨论】:
-
您是如何在不要求项目中引用 EntityFramework 的情况下使用 Context 的?
-
@krillgar model 项目应该需要它,而不是 client。客户想要参考是没有意义的。我在问为什么会这样。
标签: c# .net entity-framework