gpt4 book ai didi

c# - Dapper 通过代码 : Multi-Mapping with repeating column names 进行映射

转载 作者:行者123 更新时间:2023-12-04 01:49:13 26 4
gpt4 key购买 nike

我正在尝试执行一个简单的查询,结果数据几乎都是 null .

我有这个表结构

表注册表

ID            |  Autonumeric
TareaM_Id | Numeric
Fecha | Date/Time

和 Macro_tareas 表
ID            |  Autonumeric
Nombre | Short Text

我已经像这样映射了 C# 中的类:
[Table("Registros")]
public class Registro
{
[Column("ID")]
public virtual int ID { get; set; }

[Column("Fecha")]
public virtual DateTime Fecha { get; set; }

[Column("TareaM_Id")]
public virtual int TareaM_Id { get; set; }

public virtual MacroTarea MacroT { get; set; }
}

[Table("Macro_tarea")]
public class MacroTarea
{
[Column("ID")]
public virtual int ID { get; set; }

[Column("Nombre")]
public virtual string Nombre{ get; set; }

public virtual ICollection<Registro> Registros { get; set; }

}

这是我正在尝试使用的查询
string sql = @"SELECT reg.ID, mac.ID 
FROM Registros as reg INNER JOIN Macro_tarea as mac on reg.TareaM_Id = mac.ID
WHERE Fecha = @Fecha";

using (IDbConnection db = new OleDbConnection(ConnectionString))
{
var result = db.Query<Registro,MacroTarea, Registro>(sql,
(reg,mac) =>
{
reg.MacroTarea = mac;
return reg;
}
,new { @Fecha = new DateTime(2019, 1, 4).Date }
, splitOn: "mac.ID")
.AsList();
}

我试图只检索 id,但两个 id 都变为 null 为什么会发生这种情况?

问题是,如果我添加 Registros.FechaMacro_tarea.Nombre到查询,它正确地得到了值。但是 id 一直为空。

显然这个问题只发生在 ids 上。我怀疑这个问题是由于重复的列名造成的。

我正在与 Microsoft Access 一起工作,这很重要。

我的问题与 possible duplicate 不同因为我已经定义了应该映射的类。

最佳答案

因为您的代码无法处理数据而重命名数据库列不是一个好主意。在关注点分离的世界中,您的数据库为什么要关心?将 ID 列命名为“Id”有充分的数据库理由,您甚至可能无法更改它们。

Dapper 映射的另一个问题是重命名列无法解决。重复的类型。如果您尝试映射到类的多个实例,Dapper 会感到困惑,并且重命名列将不起作用,因为您将重命名这两个实例。

这是我想出的解决方案。它类似于许多使用字典的示例,除了:

  • 它可以嵌套到任意多个级别
  • 可应对 Dappers 7 项限制
  • 可以应付同级的重复
  • 可以重复使用,例如用于 Get、GetCurrent 和 GetAll

  • 在此示例中,有一个包含许多批处理的拍卖。每个批处理可能有 1 个或多个项目。项目可能是项目包。 Items 来自有限的目录,我们喜欢关系数据,所以 Things 表包含每个 Item 的详细信息,如颜色、尺寸等。这里我们只得到一个 Lot,但获得 Auction 与另一个级别相同在拍卖的顶部。

    参数 1 - 一次搞定一切的 SQL

    参数二 - 我们将返回的每个对象的类型数组。出于这个原因,最好命令您的 SELECT 将字段分组到类中

    参数 3 - 使用 SQL 结果调用我们即将编写的方法

    参数 4 - SQL 的标准参数数组。 SQL 注入(inject)很糟糕,可以吗?
    public async Task<List<Lot>> GetAll(int auctionId)
    {
    using (var connection = new SqlConnection(_appSettings.ConnectionString))
    {
    await connection.OpenAsync();
    var result = new List<Lot>();
    await connection.QueryAsync($@"
    SELECT [Lot].*,
    [Item].[Id],
    [Item].[LotId],
    [Item].[Notes],
    itemDetails.[Id],
    itemDetails.[ThingId],
    itemDetails.[Colour],
    itemDetails.[Size],
    [SubItem].[Id],
    [SubItem].[ItemId],
    [SubItem].[Notes],
    subItemDetails.[Id],
    subItemDetails.[ThinId],
    subItemDetails.[Colour],
    subItemDetails.[Size]
    FROM [Lot]
    INNER JOIN [Item] ON [Item].[LotId] = [Lot].[Id]
    LEFT JOIN [Thing] AS itemDetails ON itemDetails.[Id] = [Item].[ThingId]
    LEFT JOIN [SubItem] ON [SubItem].[ItemId] = [Item].[Id]
    LEFT JOIN [Thing] AS subItemDetails ON subItemDetails.[Id] = [SubItem].[ThingId]
    WHERE [AuctionId] = @{nameof(auctionId)}
    ORDER BY [Lot].[Id], [Item].[Id], [Expansion].[Id];",
    new Type[] {
    typeof(Lot),
    typeof(Item),
    typeof(Thing),
    typeof(Expansion),
    typeof(Thing)
    },
    MapResult(result),
    new
    {
    AuctionId = auctionId
    }
    );

    return result.ToList();
    }
    }

    private Func<object[], Lot> MapResult(List<Lot> result)
    {
    return (obj) =>
    {
    Lot lot = (Lot)obj[0];
    Item item = (Item)obj[1];
    Thing itemDetails = (Thing)obj[2];
    SubItem subItem = (SubItem)obj[3];
    Thing subItemDetails = (Thing)obj[4];
    if (lot != null)
    {
    if (result.Any(a => a.Id == lot.Id))
    {
    lot = result.First(a => a.Id == lot.Id);
    }
    else
    {
    result.Add(lot);
    }
    }
    if (item != null)
    {
    if (lot.Items.Any(i => i.Id == item.Id))
    {
    item = lot.Items.First(i => i.Id == item.Id);
    }
    else
    {
    lot.Items.Add(item.FromThing(itemDetails));
    }
    }
    if (expansion != null)
    {
    if (item.SubItems.Any(e => e.Id == subItem.Id) == false)
    {
    item.SubItems.Add(subItem.FromThing(subItemDetails));
    }
    }
    return null;
    };
    }

    MapResult 是代码的核心。它返回一个具有两种类型的 Func,我们在上面定义的 Type 数组和返回 Type,并接受一个顶级对象的 List。
    然后我将对象数组中的每个项目映射到另一个实际类型。这使代码更易于阅读,并且可以毫无问题地 Access 对象的属性和方法。

    然后是逐步降低层次结构的情况,在每一步检查一个是否已经存在具有匹配的 id,如果存在则将迭代器交换为对它的引用。这意味着以下代码将添加到现有项目。

    在特定情况下,我还添加了 FromThing 函数,以便更轻松地组合对象属性。

    关于c# - Dapper 通过代码 : Multi-Mapping with repeating column names 进行映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54074638/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com