如何使用通用存储库模式实现AutoMapper

时间:2018-01-14 09:07:40

标签: c# entity-framework generics asp.net-web-api automapper

我正在尝试使用Generic Repository Pattern实现AutoMapper,它包含BaseController,T类型的BaseRepository。

MapperConfig:

这是在WebAPI Project中实现AutoMapper的代码的一部分,这在App_Start()上调用

 public static class APIMapperConfig
{

    static MapperConfiguration adminConfig;

    public static IMapper adminMapper;

    public static void Configure()
    {
        ConfigureAdminConfiguration();
    }


    public static void ConfigureAdminConfiguration()
    {
        adminConfig = new MapperConfiguration(cfg => {
            cfg.CreateMap<ArticleType, DAL.ArticleType>();
            });

        adminMapper = adminConfig.CreateMapper();

        adminMapper.Map<ArticleType, DAL.ArticleType>(new ArticleType());
    }

}

APIModel(API.ArticleType)

这是API用于从客户端接收数据的模型。

public class ArticleType
    {

        public int id { get; set; }

        public String name { get; set; }

        public String displayName { get; set; }

    }

EntityModel(DAL.ArticleType)

这是EntityFramework自动生成的模型

public class ArticleType
    {

        public int id { get; set; }

        public String name { get; set; }

        public String displayName { get; set; }

    }

ArticleTypeController:(项目:API)

这是调用添加ArticleType模型的控制器,它是从T类型的BaseController派生的。

 public class ArticleTypeController : BaseController<ArticleType>
    {

        private IArticleTypeServices article;

        ArticleTypeController()
        {
            this.article = UnityConfig.ResolveObject<IArticleTypeServices>();
        }

    }

BaseController::项目(API)

这是T类型的BaseController,用于执行每个模型的Add,Update等常见任务。

    public class BaseController<T> : ApiController
        {
        IBaseRepository<T> rep;

        public BaseController()
        {
            rep= UnityConfig.ResolveObject<IBaseRepository<T>>();
        }
            [HttpPost]
            public void Add(T item)
            {
                rep.Add(item);
            }
        }

BaseRepository:(项目:DALrepository)

此存储库由BaseController调用以添加模型,此存储库调用Entity框架以添加到数据库中。

 public class BaseRepository<T> : IBaseRepository<T> where T : class
    {
        BlogDBContext db;

        public BaseRepository()
        {
            db = UnityConfig.ResolveObject<BlogDBContext>();

        }

        public void Add(T item)
        {

         // Here is the problem

    /*item which is passed from Controller is of type API.ArticleType, and what is expected to pass to entity frmawework is of type DAL.ArticleType.
       Here how do I map between API type and DAL type? It is to be noted that
ArticleType of API and DAL is already mapped inside AutoMapper code at top.*/

            this.Entities.Add(item);
            this.db.SaveChanges();
        }

当我在Fiddler(http://localhost:xxxxx/api/ArticleType)中运行它时,它会抛出错误:

实体类型ArticleType不是当前上下文模型的一部分

这很明显,因为API的ArticleType和DAL之间没有映射。

在BaseRepository Add()中发生此错误。

我认为这可能与我称之为Map&lt;&gt;的方式有关。在App_Start。

代码可能看起来很冗长,但如果我遗漏了任何东西,请告诉我。

非常感谢您的所有帮助和时间。

2 个答案:

答案 0 :(得分:2)

配置自动映射器后,您必须在代码中使用它来进行转换。在Add方法中,您只有源类型的信息,但缺少所需的目标类型。所以你需要某种类型的映射。这必须通过某种Dictionary<Type, Type>手动完成(AutoMapper的工作是自动将属性从一种类型映射到另一种类型,但不能确定最适合的目标类型)。通过提供此类信息,您可以创建如下方法:

public void Add(T item)
{
    var destinationType = _mappings[typeof(T)];
    var newEntity = _mapper.Map(item, typeof(T), destinationType);

    this.Entities.Add(newEntity);
    this.db.SaveChanges();
}

// Maybe injected through UnityConfig...
private static _mappings = new Dicionary<Type, Type> {{ typeof(API.ArticleType), typeof(DAL.ArticleType) }};

答案 1 :(得分:0)

此解决方案的工作原理是将classDto模型和EFDbset名称都传递到存储库。看这里 https://gist.github.com/mcnkbr/f96532254f62a384878f