FS0039: Пространство имен не определено

#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)
 

Теперь я могу скомпилировать решение.