Получить столбцы первой строки?

У меня есть следующий код, и я хочу, чтобы функция getCol1Col2 возвращала кортеж Col1, Col2 вместо Linq.IQueryable<>. Как это написать? Это вопрос новичка.

И как ничего не вернуть, если в таблице базы данных нет строки?

open System
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
open System.Net
open System.IO

type dbSchema = SqlDataConnection<"Data Source=server;Initial Catalog=db;Integrated Security=SSPI;">

let getFirstCol1Col2 =
    let db = dbSchema.GetDataContext()
    db.DataContext.Log <- System.Console.Out
    let query = query { 
        for row in db.MyTable do 
        where (row.ID = 1) 
        select (row.Col1, row.Col2) }
    query //.... Need to return the tuple of Col1, Col2

person ca9163d9    schedule 05.09.2013    source источник


Ответы (1)


Существует стандартный оператор запроса headOrDefault, который возвращает первый результат или значение по умолчанию. К сожалению, значение кортежа по умолчанию будет null (я думаю), так что это будет небезопасно. Вы можете вернуть тип параметра, потому что значение типа параметра по умолчанию равно None:

let query = 
  query { for row in db.MyTable do 
          where (row.ID = 1) 
          select (Some(row.Col1, row.Col2))
          headOrDefault }

Кроме того, вы можете использовать это замечательное расширение, которое добавляет headOrNone и делает именно то, что вам нужно — возвращает Some(col1, col2), если есть несколько строк. или None иначе:

let query = 
  query { for row in db.MyTable do 
          where (row.ID = 1) 
          select (Some(row.Col1, row.Col2))
          headOrNone }
person Tomas Petricek    schedule 06.09.2013
comment
Спасибо, любопытно, почему f# не может делать query.ToList().FirstOrDefault() как c# для IQueryable? - person ca9163d9; 06.09.2013
comment
@dc7a9163d9 : Можно -- не так ли open System.Linq? - person ildjarn; 06.09.2013
comment
делать ToList().FirstOrDefault() - плохая идея, если результатов несколько - это будет означать, что вы сначала загрузите все в память, а затем вернете первый. Если вы хотите сделать это в памяти, вы также можете использовать Seq.toList и сопоставление с образцом (например) - person Tomas Petricek; 07.09.2013