繁体   English   中英

Entity Framework Core 5.0 没有很好地映射 mysql 查询

[英]Entity Framework Core 5.0 is not mapping well the mysql query

我正在将 ASP.Net Core 2.1 应用程序迁移到 ASP .NET 5.0,但我在实体框架方面遇到了麻烦。 如果我在 MySQL 中执行相同的查询,我的应用程序中的结果与结果不匹配

我有这个查询

puestoCajas = _dataContext.puestocajas
    .Include(x => x.ObjSite)
    .Include(x => x.ObjCajaState)
    .Where(x => x.Enable &&
                x.SiteId == user.ObjEmployee.SiteId)
    .ToList();

查询是

SELECT `p`.`Id`, `p`.`Abrio`, `p`.`CajaMovementId`, `p`.`CajaStateId`, `p`.`Description`, `p`.`Enable`, `p`.`SiteId`, `s`.`Id`, `s`.`Address`, `s`.`CityId`, `s`.`Email`, `s`.`Enable`, `s`.`Name`, `s`.`Phone`, `c`.`Id`, `c`.`Description`, `c`.`Discriminator`
FROM `puestocajas` AS `p`
INNER JOIN `sites` AS `s` ON `p`.`SiteId` = `s`.`Id`
INNER JOIN `cajastate` AS `c` ON `p`.`CajaStateId` = `c`.`Id`
WHERE `p`.`Enable` AND (`p`.`SiteId` = 7);

我从 Visual Studio output window 复制了结果,当我直接在 MySQL 中进行操作时,结果是 // 注意 CajaStateId 和 ObjCajaState 不匹配,我可以知道为什么会这样。

ID 阿布里奥 CajaMovementId CajaStateId 描述 使能够 站点 ID ID 地址 城市编号 Email 使能够 姓名 电话 ID 描述 鉴别器
'4' '员工1' '4' '1' '普埃斯托 2' '1' '7' '7' '地址1 ' '900014' 'examplemail@gmail.com' '1' “圣米格尔” '03811234567' '1' '阿比尔塔' 'CajaOpen'

在我的应用程序中,结果如下:

In my app the result is the following: 
puestocajas [1]= {
    Abrio = "Employee1", 
    CajaMovementId=4,
    CajaMovements,
    CajaStateId = 1,
    Description = Puesto 2,
    Enable = true,
    Id=4,
    **ObjCajaState {
        Description = "Cerrada",
        Id= 2
    }**,
    ObjSite,
    SiteId
}
public class PuestoCaja
{
    public int Id 
    public string Description 
    public Site ObjSite 
    public int SiteId 
    public bool Enable 
    public CajaState ObjCajaState 
    public List<CajaMovement> CajaMovements 
    public int? CajaMovementId 
    public int CajaStateId 
    public string Abrio 
}

public abstract class CajaState
{
    public int Id {get; set;}
    public string Description {get; set;}
}

public class CajaOpened : CajaState
{
    public CajaOpened()
    {
        this.Id = 1;
        this.Description = "Abierta";
    }
}

public class CajaClosed : CajaState
{
    public CajaClosed()
    {
        this.Id = 2;
        this.Description = "Cerrada";
    }
}

不知何故,Pomelo Entity Framework Core 没有 map 导航属性。 我必须在 model 构建器中配置它们,它就是这样工作的。

您的 model 有点混乱,这就是为什么 EF Core 约定在您的导航属性及其相应的外键方面变得混乱的原因。

查看以下示例代码,它显示了您的代码和 model 的完整工作修复版本:

using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class BoxSite
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public bool Enabled { get; set; }

        public int SiteId { get; set; }
        public BoxState State { get; set; }
        public int? BoxMovementId { get; set; }

        public Site ObjSite { get; set; }
        public BoxState ObjBoxState { get; set; }
        public BoxMovement ObjBoxMovement { get; set; }
    }

    public class Site
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
        public bool Enabled { get; set; }
        
        public int CityId { get; set; }
        
        public City ObjCity { get; set; }
    }

    public class BoxMovement
    {
        public int Id { get; set; }

        public int DestinationSiteId { get; set; }
        
        public Site DestinationSite { get; set; }
    }

    public class City
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public enum BoxState
    {
        Opened = 1,
        Closed = 2,
    }

    public class Context : DbContext
    {
        public DbSet<BoxSite> BoxSites { get; set; }
        public DbSet<Site> Sites { get; set; }
        public DbSet<City> Cities { get; set; }
        public DbSet<BoxMovement> BoxMovements { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                var connectionString = "server=127.0.0.1;port=3306;user=root;password=;database=So67874766";
                var serverVersion = ServerVersion.AutoDetect(connectionString);
                optionsBuilder.UseMySql(
                        connectionString,
                        serverVersion,
                        options => options.CommandTimeout((int) TimeSpan.FromMinutes(2).TotalSeconds))
                    .UseLoggerFactory(
                        LoggerFactory.Create(
                            configure => configure
                                .AddConsole()
                                .AddFilter(level => level >= LogLevel.Information)))
                    .EnableSensitiveDataLogging()
                    .EnableDetailedErrors();
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //
            // Sample data:
            //
            
            modelBuilder.Entity<City>()
                .HasData(
                    new City {Id = 100, Name = "Paris"},
                    new City {Id = 200, Name = "Berlin"},
                    new City {Id = 300, Name = "New York"});

            modelBuilder.Entity<Site>()
                .HasData(
                    new Site {Id = 10, Name = "Paris Warehouse", Enabled = true, CityId = 100},
                    new Site {Id = 20, Name = "Berlin Warehouse", Enabled = true, CityId = 200},
                    new Site {Id = 30, Name = "New York Warehouse", Enabled = false, CityId = 300});

            modelBuilder.Entity<BoxSite>()
                .HasData(
                    new BoxSite
                    {
                        Id = 1,
                        Description = "Opened Vanilla Ice Cream Box in Paris",
                        Enabled = true,
                        SiteId = 10,
                        State = BoxState.Opened,
                    },
                    new BoxSite
                    {
                        Id = 2,
                        Description = "Closed Chocolate Ice Cream Box in Berlin",
                        Enabled = true,
                        SiteId = 20,
                        State = BoxState.Closed,
                    },
                    new BoxSite
                    {
                        Id = 3,
                        Description = "Closed Matcha Ice Cream Box New York",
                        Enabled = true,
                        SiteId = 30,
                        State = BoxState.Closed,
                    });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var berlinWarehouseSiteId = 20;

            var boxesInBerlin = context.BoxSites
                .Include(b => b.ObjSite)
                .Where(b => b.Enabled &&
                            b.SiteId == berlinWarehouseSiteId)
                .ToList();
            
            Trace.Assert(boxesInBerlin.Count == 1);
            Trace.Assert(boxesInBerlin[0].Description == "Closed Chocolate Ice Cream Box in Berlin");
        }
    }
}

它生成一个如下所示的数据库:

CREATE DATABASE `So67874766`;
ALTER DATABASE CHARACTER SET utf8mb4;

CREATE TABLE `Cities` (
    `Id` int NOT NULL AUTO_INCREMENT,
    `Name` longtext CHARACTER SET utf8mb4 NULL,
    CONSTRAINT `PK_Cities` PRIMARY KEY (`Id`)
) CHARACTER SET utf8mb4;

CREATE TABLE `Sites` (
    `Id` int NOT NULL AUTO_INCREMENT,
    `Name` longtext CHARACTER SET utf8mb4 NULL,
    `Address` longtext CHARACTER SET utf8mb4 NULL,
    `Phone` longtext CHARACTER SET utf8mb4 NULL,
    `Email` longtext CHARACTER SET utf8mb4 NULL,
    `Enabled` tinyint(1) NOT NULL,
    `CityId` int NOT NULL,
    CONSTRAINT `PK_Sites` PRIMARY KEY (`Id`),
    CONSTRAINT `FK_Sites_Cities_CityId` FOREIGN KEY (`CityId`) REFERENCES `Cities` (`Id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;

CREATE TABLE `BoxMovements` (
    `Id` int NOT NULL AUTO_INCREMENT,
    `DestinationSiteId` int NOT NULL,
    CONSTRAINT `PK_BoxMovements` PRIMARY KEY (`Id`),
    CONSTRAINT `FK_BoxMovements_Sites_DestinationSiteId` FOREIGN KEY (`DestinationSiteId`) REFERENCES `Sites` (`Id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;

CREATE TABLE `BoxSites` (
    `Id` int NOT NULL AUTO_INCREMENT,
    `Description` longtext CHARACTER SET utf8mb4 NULL,
    `Enabled` tinyint(1) NOT NULL,
    `SiteId` int NOT NULL,
    `State` int NOT NULL,
    `BoxMovementId` int NULL,
    `ObjBoxState` int NOT NULL,
    CONSTRAINT `PK_BoxSites` PRIMARY KEY (`Id`),
    CONSTRAINT `FK_BoxSites_BoxMovements_BoxMovementId` FOREIGN KEY (`BoxMovementId`) REFERENCES `BoxMovements` (`Id`) ON DELETE RESTRICT,
    CONSTRAINT `FK_BoxSites_Sites_SiteId` FOREIGN KEY (`SiteId`) REFERENCES `Sites` (`Id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;

INSERT INTO `Cities` (`Id`, `Name`)
VALUES (100, 'Paris');

INSERT INTO `Cities` (`Id`, `Name`)
VALUES (200, 'Berlin');

INSERT INTO `Cities` (`Id`, `Name`)
VALUES (300, 'New York');

INSERT INTO `Sites` (`Id`, `Address`, `CityId`, `Email`, `Enabled`, `Name`, `Phone`)
VALUES (10, NULL, 100, NULL, TRUE, 'Paris Warehouse', NULL);

INSERT INTO `Sites` (`Id`, `Address`, `CityId`, `Email`, `Enabled`, `Name`, `Phone`)
VALUES (20, NULL, 200, NULL, TRUE, 'Berlin Warehouse', NULL);

INSERT INTO `Sites` (`Id`, `Address`, `CityId`, `Email`, `Enabled`, `Name`, `Phone`)
VALUES (30, NULL, 300, NULL, FALSE, 'New York Warehouse', NULL);

INSERT INTO `BoxSites` (`Id`, `BoxMovementId`, `Description`, `Enabled`, `ObjBoxState`, `SiteId`, `State`)
VALUES (1, NULL, 'Opened Vanilla Ice Cream Box in Paris', TRUE, 0, 10, 1);

INSERT INTO `BoxSites` (`Id`, `BoxMovementId`, `Description`, `Enabled`, `ObjBoxState`, `SiteId`, `State`)
VALUES (2, NULL, 'Closed Chocolate Ice Cream Box in Berlin', TRUE, 0, 20, 2);

INSERT INTO `BoxSites` (`Id`, `BoxMovementId`, `Description`, `Enabled`, `ObjBoxState`, `SiteId`, `State`)
VALUES (3, NULL, 'Closed Matcha Ice Cream Box New York', TRUE, 0, 30, 2);

CREATE INDEX `IX_BoxMovements_DestinationSiteId` ON `BoxMovements` (`DestinationSiteId`);
CREATE INDEX `IX_BoxSites_BoxMovementId` ON `BoxSites` (`BoxMovementId`);
CREATE INDEX `IX_BoxSites_SiteId` ON `BoxSites` (`SiteId`);
CREATE INDEX `IX_Sites_CityId` ON `Sites` (`CityId`);

示例中的查询将生成以下 SQL:

SELECT `b`.`Id`, `b`.`BoxMovementId`, `b`.`Description`, `b`.`Enabled`, `b`.`ObjBoxState`, `b`.`SiteId`, `b`.`State`, `s`.`Id`, `s`.`Address`, `s`.`CityId`, `s`.`Email`, `s
`.`Enabled`, `s`.`Name`, `s`.`Phone`
FROM `BoxSites` AS `b`
INNER JOIN `Sites` AS `s` ON `b`.`SiteId` = `s`.`Id`
WHERE `b`.`Enabled` AND (`b`.`SiteId` = @__berlinWarehouseSiteId_0)

简而言之,您将 inheritance 用于 object 状态,而您不应该这样做。 您可以改用enum (如示例代码所示)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM