Я впервые рассмотрел Automapper, используя F # и Provider Entity Type. Я хочу сопоставить типы типов поставщиков EF и типы записей F #, которые я создал.Использование Automapper с провайдером Entity Type F #
ЭФ Тип поставщика основан на следующей схеме базы данных:
CREATE TABLE [dbo].[Address](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[State] [varchar](50) NOT NULL,
[County] [varchar](50) NOT NULL,
[City] [varchar](50) NOT NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Child](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[Gender] [varchar](50) NOT NULL,
[Grade] [int] NOT NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Family](
[Id] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[IsRegistered] [bit] NOT NULL,
CONSTRAINT [PK_Family] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Parent](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FamilyId] [int] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE TABLE [dbo].[Pet](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ChildId] [int] NOT NULL,
[GivenName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Pet] PRIMARY KEY CLUSTERED ([Id] ASC)
ALTER TABLE [dbo].[Address] WITH CHECK ADD CONSTRAINT [FK_Address_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_Address_Family]
ALTER TABLE [dbo].[Child] WITH CHECK ADD CONSTRAINT [FK_Child_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK_Child_Family]
ALTER TABLE [dbo].[Parent] WITH CHECK ADD CONSTRAINT [FK_Parent_Family] FOREIGN KEY([FamilyId])
REFERENCES [dbo].[Family] ([Id])
ALTER TABLE [dbo].[Parent] CHECK CONSTRAINT [FK_Parent_Family]
ALTER TABLE [dbo].[Pet] WITH CHECK ADD CONSTRAINT [FK_Pet_Child] FOREIGN KEY([ChildId])
REFERENCES [dbo].[Child] ([Id])
ALTER TABLE [dbo].[Pet] CHECK CONSTRAINT [FK_Pet_Child]
Затем я создал сопоставимый набор типов в F #:
type Pet = {Id:int; GivenName:string}
type Child = {Id:int; FirstName:string; Gender:string; Grade:int; Pets: Pet list}
type Address = {Id:int; State:string; County:string; City:string}
type Parent = {Id:int; FirstName:string}
type Family = {Id:int; Parents:Parent list; Children: Child list; Address:Address}
Единственное реальное отличие состоит в том, что внешний ключ не является явным в типах записей.
Когда я использую Automapper от типа адреса, он работает, как ожидалось:
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
let context = EntityConnection.GetDataContext()
let addressQuery = query {for address in context.Addresses do select address}
let address = Seq.head addressQuery
let address' = Mapper.Map<Address>(address)
val address' : Address = {Id = 1;
State = "WA";
County = "King";
City = "Seattle";}
Но когда я пытаюсь сделать то же самое со всем графом,
Mapper.CreateMap<EntityConnection.ServiceTypes.Pet, Pet>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Child, Child>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Address, Address>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Parent, Parent>()
Mapper.CreateMap<EntityConnection.ServiceTypes.Family, Family>()
let context = EntityConnection.GetDataContext()
let familyQuery = query {for family in context.Families do select family}
let family = Seq.head familyQuery
let family' = Mapper.Map<Family>(family)
Я получаю это исключение:
System.ArgumentException: Type needs to have a constructor with 0 args or only optional args
Parameter name: type
мне интересно, если это б/с EF является отложенной загрузки, так что остальные типы не будучи ева luated? Кто-нибудь видел это раньше?
Могу ли я рекомендовать демпинг AutoMapper с панели инструментов, если вы заботитесь о чувственных типов в ваших программах. –
бит старый, но что произойдет, если вы не используете список FSharp и используете массив в своих определениях записи. Вещи могут начать работать, поскольку массив - это не определенный тип F #. –
@GregC Альтернатива - это написать код. Это лучше, потому что компилятор может проверять вещи, и вы можете рассуждать о своем коде. Другой альтернативой были бы макросы времени компиляции, но это еще не очень хорошо поддерживается в .NET. –