在调用时DbContext.SaveChanges,我得到一个DbUpdateException:
EntityFramework.dll中发生了未处理的"System.Data.Entity.Infrastructure.DbUpdateException"类型异常.附加信息:更新条目时发生错误.有关详细信息,请参阅内部异常
不幸的是,没有内在的例外(至少,不是我能看到的).有没有办法确切地知道为什么SaveChanges抛出异常?至少,看看SaveChanges在发生错误时尝试更新的表格会很有帮助.
我正在尝试在IEnumerable上应用Seq函数.更具体地说,它是System.Windows.Forms.HtmlElementCollection实现ICollection和IEnumerable.
由于F#seq是IEnumerable,我以为我可以写
let foo = myHtmlElementCollection |> Seq.find (fun i -> i.Name = "foo")
Run Code Online (Sandbox Code Playgroud)
但编译器将没有它,并抱怨"类型'HtmlElementCollection'与类型'seq <'a>'"不兼容.
但是,编译器愿意在for .. in ..序列表达式中接受IEnumerable :
let foo = seq { for i in myHtmlElementCollection -> i } |> Seq.find (fun i -> i.Name = "foo")
Run Code Online (Sandbox Code Playgroud)
为了让IEnumerable像任何旧的F#一样被处理,我需要做什么seq?
注意:这个问题被标记为重复,但事实并非如此.链接的"重复"是关于无类型序列(来自seq {for ...}表达式的seq),而我的问题是关于类型化序列.
在VS2010中,如果使用错误的调用约定调用函数,则托管调试助手将为您提供pInvokeStackImbalance异常(pInvokeStackImbalance MDA),这通常是因为在调用C库时未指定CallingConvention = Cdecl.比如你写的
[DllImport("some_c_lib.dll")]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
代替
[DllImport("some_c_lib.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
因此获得了StdCall调用约定而不是Cdelc.
如果你回答这个问题,你已经知道了这个差异,但是对于这个线程的其他访问者:StdCall意味着被调用者清除堆栈中的参数,而Cdecl意味着调用者清理堆栈.
因此,如果您的C代码中的调用约定错误,则您的堆栈不会被清理并且程序崩溃.
但是,即使.NET程序使用StdCall进行Cdecl功能,.NET程序似乎也不会崩溃.默认情况下,VS2008上没有启用堆栈不平衡检查,因此一些VS2008项目使用了他们的作者不知道的错误调用约定.我刚尝试过GnuMpDotNet,即使缺少Cdelc声明,样本运行也很好.X-MPIR也是如此.
它们都在调试模式下抛出pInvokeStackImbalance MDA异常,但在发布模式下不会崩溃.为什么是这样?.NET VM是否将所有对本机代码的调用包装起来并在之后恢复堆栈本身?如果是这样,为什么还要使用CallingConvention属性呢?
当F#记录的字段部分被声明为私有时,我才注意到一种相当反直觉的行为.(这与是否有可能使记录的字段成为私有?或使记录成员成为私有的?)
在这个例子中......
type MyRec =
private // Fields declared private, or at least I thought so.
{ a : int
b : int }
member x.A = x.a
member private x.Both = x.a + x.b
static member CreateMyRec(a, b) = { a = a; b = b }
let foo = MyRec.CreateMyRec(1,2)
let bar = foo.a // No error. Huh?
let baz = foo.Both // Error: not accessible.
Run Code Online (Sandbox Code Playgroud)
... Both正如预期的那样,私有成员在类型声明范围之外是不可访问的.但是,该字段a是可访问的.
如果将MyRec放入模块中,则该字段将成为该模块的私有字段.这就是你期望模块中的顶级声明表现的方式,但是我预计在一个类型中声明为private的任何东西都是该类型的私有,而不是它的封闭模块.
这种行为实际上是不是很奇怪,或者我在这里的推理中遗漏了什么?
如果我指定我想要默认的构建和修订号,我就说
[<assembly: AssemblyVersion("0.0.*")>]
Run Code Online (Sandbox Code Playgroud)
在AssemblyInfo.fs中(我基于https://blogs.msdn.com/b/mcsuksoldev/archive/2011/06/01/f-assembly-information-file-template.aspx上的示例).
出于某种原因,我总是0.0.4967.0在F#DLL中以版本号0(例如)结束,而它的工作方式与C#(例如0.0.4967.21937)中的广告相同.
默认修订号仅在内部版本号不是通配符时才有效0.0.1.*.
这是一个错误还是我错过了什么?
如果使用Observable创建Observable.Timer(),你如何阻止它?
let tmr = Observable.Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds 1000.)
let subscription = tmr.Subscribe(myFunction)
// ...
subscription.Dispose()
Run Code Online (Sandbox Code Playgroud)
你是否甚至需要阻止它,或者当它的所有用户都被处理掉后它会被垃圾收集?
我在.NET 4.0项目中使用FSharp.Data.1.1.10,当我使用Nuget添加FSharp.Data时,它会创建一个packages\FSharp.Data.1.1.10\lib \net40目录,它放置FSharp. Data.dll和FSharp.Data.DesignTime.dll.根据Telerik JustDecompile,FSharp.Data.dll是一个.NET 4.0 dll,但FSharp.Data.DesignTime.dll是一个.NET 4.5 dll,即使它位于net40子目录中.
那么,只有FSharp.Data.DesignTime .NET 4.5,还是这个bug?
将F#中缀运算符放在括号中,它的行为类似于函数,
let foo = (*) 3 2 // foo = 6
let factorial n = [2..n] |> List.fold (*) 1 // n!
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于:: operator(cons运算符),
let ls = (::) 1 [2..5] // Error: Unexpected symbol '::' in binding.
Run Code Online (Sandbox Code Playgroud)
这是什么原因?
这与我如何在不引入竞争条件的情况下等待来自RX主题的响应相同?,但在F#.
C#解决方案看起来像:
static async void Foo()
{
var subject = new Subject<int>();
var firstInt = subject.FirstAsync().PublishLast();
firstInt.Connect();
subject.OnNext(42);
var x = await firstInt;
Console.WriteLine("Done waiting: " + x);
}
Run Code Online (Sandbox Code Playgroud)
我在F#的尝试是这样的:
let foo () =
async {
use subject = new Subject<int>()
let firstInt = subject.FirstAsync().PublishLast()
firstInt.Connect() |> ignore
subject.OnNext(42)
let! x = firstInt
printfn "Done waiting: %d" x
return ()
}
Run Code Online (Sandbox Code Playgroud)
在let x! = firstInt给出了编译错误This expression was expected to have type Async<'a> but …
您是否需要将返回的IDisposable分配给IObservable.Subscribe变量以保护订阅不被垃圾回收,或者是否存在足够的活动订阅?
我的用例:我从现有的observable(myObservable在示例中)中创建一次性observable :
myObservable.Take(1).Subscribe(fun v -> printfn "One-shot: %A" v) |> ignore
Run Code Online (Sandbox Code Playgroud) 我在VS2010中尝试了以下代码:
open System.Security.Cryptography
let rsaTest1 =
let ecKey = [|0uy..143uy|] // junk data for testing
let ecKeyMod = ecKey.[8..8+128-1]
let ecKeyExp = ecKey.[136..136+8-1]
let rsa = RSAParameters(Modulus = ecKeyMod, Exponent = ecKeyExp)
rsa
let rsaTest2 =
let ecKey = [|0uy..143uy|] // junk data for testing
let rsa = RSAParameters(Modulus = ecKey.[8..8+128-1], Exponent = ecKey.[136..136+8-1])
rsa
Run Code Online (Sandbox Code Playgroud)
如果我突出显示所有代码并将其发送到F#Interactive(Alt + Enter),则rsaTest1可以工作,但rsaTest2会给出错误消息,
System.NullReferenceException: Object reference not set to an instance of an object.
at <StartupCode$FSI_0004>.$FSI_0004.main@() in P:\proj\Tachograph\Project\CompuTachTest\CompuTachTest\rsaTest.fsx:line 16
Run Code Online (Sandbox Code Playgroud)
但是,如果我将rsaTest2从值更改为函数并调用它,
let rsaTest2 () =
let …Run Code Online (Sandbox Code Playgroud) 我在构造函数中创建一个计时器,并希望使计时器成为构造类的成员.由于计时器未被任何其他类成员引用,因此它被编译为构造函数本地的变量,因此垃圾被收集和终止.
防止这种情况发生的一种方法是制作虚拟参考,例如
type MyClass() as o =
let timer = new Timer((fun _ -> o.Tick()), null, 0, 1000)
member private o.DummyRef = timer
member o.Tick() = printfn "Tick!"
Run Code Online (Sandbox Code Playgroud)
有没有更简洁的方式强迫timer成为会员?