F#Linq To SQL提交更改不会执行任何操作

Bar*_*osz 3 f# linq-to-sql

我已经在F#中定义了以下类,具有Linq到SQL的映射属性:

[<Table(Name="Expense")>]
type public Expense(datetime : Nullable<DateTime>, value, category, comment) = 
    let mutable id = 0
    let mutable datetime = if datetime.HasValue then datetime.Value else DateTime.Now
    let mutable value = value
    let mutable category = category
    let mutable comment = comment
    [<Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)>]
    member x.ExpenseID with get() = id and set v = id <- v
    [<Column>]
    member x.DateTime with get() = datetime and set v = datetime <- v
    [<Column>] 
    member x.Value with get() = value and set v = value <- v
    [<Column>] 
    member x.Category with get() = category and set v = category <- v    
    [<Column>] 
    member x.Comment with get() = comment and set v = comment <- v
    new() = Expense(nl, 0m, "", "")
Run Code Online (Sandbox Code Playgroud)

然后我想使用以下代码(片段)插入该类型的新对象:

member private x.expenses = (new DataContext(connString)).GetTable<Expense>()
    member x.Add (expense : Expense) = 
        x.expenses.InsertOnSubmit(expense)
        x.expenses.Context.SubmitChanges()
Run Code Online (Sandbox Code Playgroud)

调用SubmitChanges()不会执行任何操作,也不会抛出任何异常.所以我试着检查,如果它有一个F#对象的东西,我已经在C#中声明了其他类,具有完全相同的映射.然后我能够插入新的记录.现在我想知道,有什么区别?

做了一些Reflector调查,唯一的区别是C#auto getters/setter上的[CompilerGenerated]属性,以及F#类上的[Serializable]和CompilationMapping(SourceConstructFlags.ObjectType)]可能是其中之一吗?

反射器拆卸:http://pastebin.com/qTRfVcmm

//编辑

通过对.NET框架代码进行一些调试,我注意到DataContext实例的跟踪对象的内部列表在InsertOnSubmit和SubmitChanges调用之间不一致.在SubmitChanges调用开始时,此列表为空.这让我想到,这两个引用并没有针对相同的DataContext实例,VS调试器确认了这一点.不过,不知道为什么.

Tom*_*cek 6

问题是第一次使用member.F#成员(没有参数)表现得像属性,所以每次访问时都要创建新的数据上下文x.expenses.要更正此问题,您可以使用let以下方法将表对象存储在字段中:

type SomeType() =
  let expenses = (new DataContext(connString)).GetTable<Expense>()     
  member x.Add (expense : Expense) =          
    expenses.InsertOnSubmit(expense)
    expenses.Context.SubmitChanges() 
Run Code Online (Sandbox Code Playgroud)

member x.Foo = <expr>F#中的语法对应于具有getter的属性,因此在C#语法中,您的原始代码如下所示:

Table<Expenses> Expenses {
  get { return (new DataContext(connString)).GetTable<Expense>(); }
}
Run Code Online (Sandbox Code Playgroud)

...这解释了为什么创建了多个数据上下文副本.