异常抛出:实体数据模型对象实例化时 C# Windows 服务中的“System.IO.FileNotFoundException”

Posted

技术标签:

【中文标题】异常抛出:实体数据模型对象实例化时 C# Windows 服务中的“System.IO.FileNotFoundException”【英文标题】:Exception Thrown: 'System.IO.FileNotFoundException' in C# Windows Service When Entity Data Model Object Instantiated 【发布时间】:2021-12-06 17:24:51 【问题描述】:

Windows Server 2012 R2 Standard 上运行是使用我编写的 Entity FrameworkC# Windows 服务 (.Net Framework 4.7.2)它从文件中读取数据并将数据传递到本地 SQLExpress (2016) 存储过程,以将数据插入数据库。

虽然在我的 Windows 10 机器上测试它工作正常,但在将可执行文件和 exe.config 移动到 Windows 服务器并使用连接字符串中正确的数据库信息更新配置后,事件查看器显示以下 Windows 应用程序错误:

来源:.NET 运行时事件 1026

Application: Print_Mail-DBAuger.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
   at Print_Mail_DBAuger.Program.StartParseAndInsert(System.String, System.Diagnostics.EventLog)
   at Print_Mail_DBAuger.FetchService.OnChanged(System.Object, System.IO.FileSystemEventArgs)
   at System.IO.FileSystemWatcher.OnCreated(System.IO.FileSystemEventArgs)
   at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32, System.String)
   at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32, UInt32, System.Threading.NativeOverlapped*)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

这似乎阻止了存储过程被调用,因此没有数据被传递到数据库。

我已将问题缩小到实体数据模型对象的实例化:

PrintMailEntities dataEntities = new PrintMailEntities();

此行调用由实体框架创建的自动生成代码:

public partial class PrintMailEntities : DbContext
    
        public PrintMailEntities()
            : base("name=PrintMailEntities")
        
        
        
        // Several more auto-generated methods...
    

还有超类构造函数(同样,实体框架的一部分,不是我的代码):

public class DbContext : IDisposable, IObjectContextAdapter
    
        //
        // Summary:
        //     Constructs a new context instance using the given string as the name or connection
        //     string for the database to which a connection will be made. See the class remarks
        //     for how this is used to create a connection.
        //
        // Parameters:
        //   nameOrConnectionString:
        //     Either the database name or a connection string.
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
        [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public DbContext(string nameOrConnectionString);

        // Other overrloaded constructors not used...
     

此行之前的程序中的所有内容都按预期工作(我使用了几个应用程序事件日志来跟踪正在发生的事情,因为我在 Windows Server 上没有 Visual Studio 可用于调试。)我的文件尝试阅读不是问题,我可以很好地阅读该信息。

我也尝试用 try/catch 包围实例化以捕获 FileNotFoundException,但从未触发 catch。我还镜像了 Windows Server DB 的数据库权限以匹配我的本地计算机 DB 的权限,并以管理员权限运行。

这是 Windows Server exe.config 中的连接字符串:

<connectionStrings>
        <add name="PrintMailEntities" connectionString="metadata=res://*/DataModel.csdl|res://*/DataModel.ssdl|res://*/DataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=machineName\HPWJA;initial catalog=PrintMail;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    </connectionStrings>

同样,这在 Windows 10 上运行良好,连接字符串指向一个镜像 Windows Server 数据库的数据库。我的机器上没有构建错误,Windows Server 上也没有 SQL Server 日志表明数据库端发生了任何错误。

编辑

感谢 RB,我现在有更多关于无法找到的“文件”的详细信息。这是更新的事件日志。

Error: Could not load file or assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.
   at Print_Mail_DBAuger.Program.StartParseAndInsert(String inputFile, EventLog programEventLog)
   at Print_Mail_DBAuger.FetchService.OnChanged(Object sender, FileSystemEventArgs e)
EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 was missing.

错误似乎是在引用 app.config 中的节元素

<configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>

服务器没有网络,可能是试图从网上拉取nuget包?

【问题讨论】:

问题出在调用堆栈中。 - Program.StartParseAndInsert(System.String, System.Diagnostics.EventLog) - FetchService.OnChanged(System.Object, System.IO.FileSystemEventArgs) 如果我没记错的话,Windows 服务的基本目录是 C:\Windows,无论路径如何你的 .exe 是。因此,如果您尝试使用相对路径加载文件,则可能会失败。 Hazrelle,直到实体数据模型对象实例化点之前的可执行文件的其余部分工作正常。并且服务属性“可执行文件路径”是绝对路径。我错过了什么吗?感谢您的评论。 在整个 StartParaeAndInsert 方法周围放置一个 try...catch(FileNotFoundException e)...。注销找不到的文件的名称。届时您将获得问题的答案。 看起来您正在使用 FileWatcher,在文件到达和尝试读取文件之间是否存在延迟?我以前遇到过这种情况,这是因为事件在文件创建后立即触发,但创建它的进程仍在写入它,并且在尝试读取它时锁定它。这通常不会在您的机器上进行测试时出现,因为文件通常较小且是本地文件,而不是较大并通过网络写入。通常几百毫秒就足够了。 RB,所以 try/catch 确实起作用了(我不知道为什么当我只包围对象实例时它不起作用,因为这就是 StartParseAndInsert 方法所做的一切)。但无论如何,我确实从中得到了日志,看起来这是 EF 的问题。将编辑原始帖子以显示新日志。再次感谢! 【参考方案1】:

问题是我缺少在构建输出的 Release 目录中找到的 EntityFramework.dll。添加 EntityFramework.dll 和 EntityFramework.SqlServer.dll 解决了这个问题。感谢 RB 帮我找到这个。

【讨论】:

以上是关于异常抛出:实体数据模型对象实例化时 C# Windows 服务中的“System.IO.FileNotFoundException”的主要内容,如果未能解决你的问题,请参考以下文章

VS2015 在添加新的实体数据模型时抛出异常

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

反射异常 java.lang.InstantiationException处理

C# Serializable

dll Matlab实例在c#中运行release时抛出异常

如何在实例化时将值插入 C# 字典?