0

我提交这个问题有两个原因:我在使用DBreeze在 下运行的数据库引擎时遇到了困难Mono,但我找到了一种解决方法,它可以帮助其他人解决这个确切的问题(我将解决方法作为答案发布),如果有人否则知道更好的解决方案,我将感谢您的帮助。

问题是DBreeze在 Windows 上正常工作,但在带有 Mono 的 Linux 上,在引擎初始化之后,第一次插入它会引发以下异常:

Unhandled Exception: DBreeze.Exceptions.DBreezeException: Getting table "@utt2"
from the schema failed! ---> DBreeze.Exceptions.TableNotOperableException:
DBreeze.Scheme ---> DBreeze.Exceptions.DBreezeException: Rollback of the table
"DBreeze.Scheme" failed! ---> DBreeze.Exceptions.DBreezeException: Restore
rollback file "./DB/_DBreezeSchema" failed! --->
System.EntryPointNotFoundException: FlushFileBuffers

问题出在DBreeze/Storage/FSR.cs文件中,因为它试图调用

    [System.Runtime.InteropServices.DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool FlushFileBuffers(IntPtr hFile);

但这在 Mono 中不受支持。

问题是:如何正确刷新文件缓冲区/调用与 kernel32.dll 等效的文件FlushFileBuffers()以将缓冲区内容写入 Mono 下的磁盘?

4

2 回答 2

1

我的解决方法如下:

由于此方法会将数据从 OS 文件缓冲区同步到硬盘驱动器(或任何块设备),本机 unixfsync方法能够做同样的事情。

对我有用的解决方法是用自定义函数替换上面的 DllImport:

        // [System.Runtime.InteropServices.DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
        // private static extern bool FlushFileBuffers(IntPtr hFile);
        private static bool FlushFileBuffers(IntPtr handle)
        {
            return Mono.Unix.Native.Syscall.fsync(handle.ToInt32()) == 0 ? true : false;
        }

fsync0如果没有错误则返回,-1如果有错误,则必须将句柄强制转换为intfrom IntPtr

在编译期间,/r:Mono.Posix.dll必须在命令行中添加参数才能访问fsync本机系统调用。

我不完全确定这个技巧是否会完全按照原始代码中的预期工作,因为根据操作系统刷新缓冲区有不同的级别,所以请告诉我是否有更好/正确的解决方案来解决这个问题,或者这个我发现的解决方案完全合适。

于 2018-03-17T08:44:44.327 回答
0

对于 .net40 及更高版本,您可以使用函数。

#if NET40
    public static void NET_Flush(FileStream mfs)
    {
        mfs.Flush(true);
    }
#else

    [System.Runtime.InteropServices.DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool FlushFileBuffers(IntPtr hFile);

    public static void NET_Flush(FileStream mfs)
    {
        mfs.Flush();
        IntPtr handle = mfs.SafeFileHandle.DangerousGetHandle();

        if (!FlushFileBuffers(handle))
            throw new System.ComponentModel.Win32Exception();
    }
#endif
于 2018-04-20T05:29:25.323 回答