#f# #fsharp.data.sqlclient
Вопрос:
Я создаю веб-API в F#, чтобы проверить некоторые вещи. Я родом из C#, и я структурировал вещи так, как я это делаю.
Вы можете найти репо здесь: https://github.com/MrGodlike6/WebApiTest
Я ссылался на WebApiTest.Репозитории.Проект SQLServer в WebApiTest.WebAPI, но по какой-то причине Visual studio говорит, что не может найти репозитории WebApiTest..Пространство имен SQLServer.
Дело в том, что решение отлично компилируется, и я могу запустить приложение, просто у меня нет IntelliSense для всего, что исходит из проекта SQLServer (например, в модуле CompositionRoot).
Я перепробовал много вещей, от разных баз данных, до создания проекта .NET Framework 4.7.2 для проекта БД. Пока ничего не работает. Пробовал и Nuget, и пакет, и никакой разницы. Пробовал ПРОТИВ 2019 года. В VS 2022 это дает некоторую ошибку компиляции, которая не связана.
Я использовал dotPeek из JetBrains, чтобы посмотреть на результат .библиотека dll и пространство имен и модуль находятся там, как и ожидалось. Не знаю, что может быть причиной этого.
Также можете ли вы указать, подходит ли структура проекта/папок, которую я использую, для F#? Любые другие предложения также приветствуются.
ИЗМЕНИТЬ: Часть SQL основана на https://github.com/isaacabraham/get-programming-fsharp/tree/master/src/code-listings/lesson-35. Здесь все работает, хотя SQL-код не помещен в отдельный проект.
Я прокомментировал SqlEnumProvider, и у меня больше нет проблем с корнем композиции. Я посмотрю немного внимательнее на этого провайдера и посмотрю, смогу ли я что-нибудь придумать.
EDIT2: Создал проблему на GitHub: https://github.com/fsprojects/FSharp.Data.SqlClient/issues/410
Комментарии:
1. У вас есть SQL для заполнения базы данных? Я не могу скомпилировать ваше решение, потому что поставщики типов в репозиториях WebApiTest. sqlserverу не над чем работать.
2. Итак, тип идентификатора операции в соответствующих таблицах репо является целочисленным. Можете ли вы проверить, есть ли у вас правильные типы в настройках?
3. Я попробовал как базу данных, созданную сценариями в репозитории книги (localdb), так и создать новую базу данных в docker с той же схемой, но безуспешно. И код SqlEnumProvider такой же, как и в книжном репозитории.
Ответ №1:
Я воспроизвел то, что вы видите. Проблема, по-видимому, вызвана ошибкой во время проектирования в FSharp.Поставщик типов данных. В частности, SqlEnumProvider
похоже, что это источник. Когда я удаляю DbOperations
тип из AccountRepository.fs (используя простые строки вместо значений перечисления), я могу получить Intellisense для WebApiTest.Repositories.SqlServer
в CompositionRoot.fs.
Вот мой дурацкий обходной путь:
[<AutoOpen>]
module private DB =
let [<Literal>] Conn = @"Data Source=.;Database=BankAccountDb;Integrated Security=True;Connect Timeout=60"
type AccountsDb = SqlProgrammabilityProvider<Conn>
type GetAccountId = SqlCommandProvider<"SELECT TOP 1 AccountId FROM dbo.Account WHERE Owner = @owner", Conn, SingleRow = true>
type FindTransactions = SqlCommandProvider<"SELECT Timestamp, OperationId, Amount FROM dbo.AccountTransaction WHERE AccountId = @accountId", Conn>
type FindTransactionsByOwner = SqlCommandProvider<"SELECT a.AccountId, at.Timestamp, at.OperationId, at.Amount FROM dbo.Account a LEFT JOIN dbo.AccountTransaction at on a.AccountId = at.AccountId WHERE Owner = @owner", Conn>
// type DbOperations = SqlEnumProvider<"SELECT Description, OperationId FROM dbo.Operation", Conn>
let toBankOperation operationId =
match operationId with
| "Deposit" -> Deposit
| "Withdraw" -> Withdraw
| _ -> failwith "Unknown operation!"
let fromBankOperation bankOperation =
match bankOperation with
| Deposit -> "Deposit"
| Withdraw -> "Withdraw"
Я искал существующую проблему на GitHub, но не нашел ее, так что вы, возможно, захотите открыть новую самостоятельно.
Если кто-то еще хочет попробовать это, вот схема фиктивной базы данных, которую я использовал для компиляции:
USE [BankAccountDb]
GO
/****** Object: Table [dbo].[Account] Script Date: 9/16/2021 11:40:48 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Account](
[Owner] [nchar](10) NOT NULL,
[AccountId] [uniqueidentifier] NOT NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[AccountTransaction] Script Date: 9/16/2021 11:40:48 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AccountTransaction](
[AccountId] [uniqueidentifier] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[OperationId] [nchar](10) NOT NULL,
[Amount] [money] NOT NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Operation] Script Date: 9/16/2021 11:40:48 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Operation](
[Description] [nvarchar](100) NULL,
[OperationId] [nvarchar](100) NULL
) ON [PRIMARY]
GO
Ответ №2:
Спасибо тебе, Брайан, за сценарий.
Как говорится в документации,
«Тип перечисления (или тип перечисления) — это тип значения, определяемый набором именованных констант базового интегрального числового типа«.
Я изменил OperationId
тип данных столбца на int в dbo.Operation
и dbo.AccountTransaction
и заполнил таблицу dbo.Операция, потому SqlEnumProvider
что жаловался на отсутствие данных во время компиляции.
CREATE TABLE [dbo].[Operation] (
[Description] NVARCHAR (100) NULL,
[OperationId] INT NOT NULL
);
CREATE TABLE [dbo].[AccountTransaction] (
[AccountId] UNIQUEIDENTIFIER NOT NULL,
[Timestamp] DATETIME NOT NULL,
[OperationId] INT NOT NULL,
[Amount] MONEY NOT NULL
);
insert dbo.Operation (Description, OperationId) values ('Deposit', 1), ('Withdraw', 2)
Теперь я могу скомпилировать решение.