首页 > 解决方案 > AutoMapper 复制 EF 连接的对象,无需一行和几行代码

问题描述

这有点长,所以给自己喝杯咖啡(也可以提供其他优质饮品)。

为了尽可能少地编写代码,让我的应用程序保持简单、可测试、可维护和干净,并让应用程序快速运行。

我正在使用我编写的一种非常简单的方法来从 MVC 对象复制到 EF 对象,以在我拥有具有大量属性的对象时节省我编写大量代码的时间。事实上,我不在乎对象是什么或它有多少属性。我只想复制它而不在地图或某处准备大量代码。

请不要从视图模型和所有这些开始,并引用我的微软大书。所有我正在寻找来自我的同行和整个社区的关于AutoMapper的一点建议 这里的例子很简单,所以你可以看到我在做什么。

我不想做的,我已经看过很多了,是:-

item ... //the original item populated from somewhere, MVC database, who cares, its got stuff in it

Item newItem = new Item();

newItem.prop1 = item.prop1;
newItem.prop2 = item.prop2;
newItem.prop3 = item.prop3;
newItem.prop4 = item.prop4;
//... you get the idea

甚至这个...

Item newItem = new Item {  
    prop1 = item.prop1,
    prop2 = item.prop2,
    prop3 = item.prop3,
    prop4 = item.prop4,
    //... you get the idea
}

所以我想出了这个。一个名为CopyObject的函数可以完美地完成我想要它做的事情,所以我不必关心任何对象或它有多少属性,我在任何需要的地方编写一行代码就可以为我完成所有工作。请参阅下面的示例

//show the item in a view, typically a bootstrap popup dialog
public IActionResult EditItem(int ID)
{
    Item item = _dbContext.Items.Where(i => i.ID == ID).FirstOrDefault();

    if (item == null)
        item = new Item { ... property defaults ... };

    return View(item);
}

//save the item from the view
[HttpPost]
public JsonResult EditItem(Item item)
{
    Item newItem = _dbContext.Item.Where(i => item.ID).FirstOrDefault();
    if (newItem == null)
    {
        newItem = newItem {... property defaults ... };
        _dbContext.Items.Add(newItem);
    }

    //here is the fun part
    CopyObject(item, newItem, ...ignore some properties);

    _dbContext.SaveChanges();

    return new JsonResult( new { result = "success", message = "Updated" });
}

CopyObject是我的函数,除了它使用反射将属性从一个对象复制到另一个(EF)对象而不会丢失与 EF 的连接之外,它并没有什么聪明之处。CopyObject 看起来像这样(下图)。我不会对实现感到厌烦,但简单地说,它使用反射在任意两个对象之间复制属性。

目前它只从顶层复制,因为这就是我现在需要它做的所有事情,但让它复制一个层次结构并不是一件容易的事。

它实际上并不关心对象类型是否匹配,它并不关心属性类型是否匹配。它只关心是否在每个对象上找到具有相同名称的属性,然后它会尝试复制这些值。您还可以指定不复制的属性。

    /// <summary>
    /// Copies the values of the properties from one object to another object with the same properties if they exist.
    /// This will try to copy from any two objects whether they are the same object type or not
    /// </summary>
    /// <param name="CopyFrom">The object to copy property data from</param>
    /// <param name="CopyTo">The object to copy property data to</param>
    /// <param name="DontCopy">A (string) list field names not to be copied</param>
    /// <returns>True if at least one property was copied, otherwise false</returns>
    public bool CopyObjects(object CopyFrom, object CopyTo, params string[] DontCopy) {...}

我的代码没有任何问题,它完全按照我需要的方式工作。当我开始一个新项目时,无论任何对象有多少属性,我都没有任何额外的工作要做。我只是导入那个

无论如何,因为我没有发表或任何形式的权威,我的代码被不赞成。我被告知AutoMapper可以做同样的事情,但我似乎做不到。我总是得到一个断开连接的对象,然后我必须做一些愚蠢的事情才能将其重新放入 EF 并最终返回数据库。

所以我的问题是。您如何在没有大量代码的情况下使用 Automapper 实现相同的目标?请记住,我的目标是不必编写大量代码,无论是在准备中还是在行中。

标签: c#entity-frameworkasp.net-corereflectionautomapper

解决方案


NameAutoMapper 可以使用以下代码忽略属性(例如在以下示例中)

public class MyProfile : Profile
{
    public MyProfile ()
    {
        CreateMap<Item, Item>().ForMember(x => x.Name, opt => opt.Ignore()) ;

    }
}

你的行动:

var newItem = _mapper.Map<Item, Item>(item);

参考

忽略使用 Automapper 映射一个属性

https://medium.com/ps-its-huuti/how-to-get-started-with-automapper-and-asp-net-core-2-ecac60ef523f


推荐阅读