So I created a really simple domain model that looks like this:
The repository code looks like this:
public class PhotoRepository : IDisposable
{
private readonly PhotosDataContext _dc;
public PhotoRepository()
{
Registry.AutoMapperRegistry.Configure();
_dc = new PhotosDataContext();
}
public List<Photo> GetAll()
{
return Mapper.Map<PhotoDataModel[], Photo[]>(_dc.PhotoDataModels.ToArray()).ToList();
}
public void Save(Photo photo)
{
Registry.AutoMapperRegistry.Configure();
using (var dc = new PhotosDataContext())
{
dc.PhotoDataModels.InsertOnSubmit(Mapper.Map<Photo, PhotoDataModel>(photo));
dc.SubmitChanges();
}
}
public void Dispose()
{
if (_dc != null)
_dc.Dispose();
}
}
So in the implementation project, I added my AutoMapper configuration. I setup two profiles one for the LINQtoSQL and then one to reverse it. Here's that code:
public class AutoMapperRegistry
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<LinqToSqlProfile>();
x.AddProfile<LinqToSqlReverseProfile>();
});
}
}
public class LinqToSqlProfile : Profile
{
protected override string ProfileName
{
get
{
return "LinqToSqlProfile";
}
}
protected override void Configure()
{
Mapper.CreateMap<PhotoDataModel, Photo>()
.ForMember(dest => dest.Photographer, opt => opt.MapFrom(src=>src.PhotographerDataModel));
Mapper.CreateMap<PhotographerDataModel, Photographer>();
}
}
public class LinqToSqlReverseProfile:Profile
{
protected override string ProfileName
{
get
{
return "LinqToSqlReverseProfile";
}
}
protected override void Configure()
{
Mapper.CreateMap<Photo, PhotoDataModel>()
.ForMember(dest => dest.PhotographerDataModel, opt => opt.MapFrom(src => src.Photographer));
Mapper.CreateMap<Photographer, PhotographerDataModel>();
}
}
You'll notice in my repository I call the configure method twice once in the constructor and again on the save. I didn't have to do it in the save, but the way I did the console app, it was required. I could've called it before calling the save, but I wanted it all in one place to make it a little easier to read...I think it is anyhow.
So in order to flatten out my domain model like Headspring seems to practice and I try to mimic everything they do because lets face it, they're the best software company in the world. At least that's my opinion. So here is my view model:
public class PhotoViewModel
{
public string Name { get; set; }
public string FileSize { get; set; }
public DateTime DateTaken { get; set; }
public string Description { get; set; }
public string PhotographerName { get; set; }
}
Here is my AutoMapper configuration for the UI project:
public class ViewProfile:Profile
{
protected override string ProfileName
{
get{ return "ViewProfile"; }
}
protected override void Configure()
{
Mapper.CreateMap<Core.Photo, PhotoViewModel>()
.ForMember(dest => dest.PhotographerName, opt => opt.MapFrom(src => src.Photographer.Name));
}
}
Here's the initialization:
public class AutoMapperRegistry
{
public static void Configure()
{
Mapper.Initialize(x => x.AddProfile<ViewProfile>());
}
}
Finally, here is my UI code that displays a list of the photographers and then saves a new one.
static void Main(string[] args)
{
var pr = new PhotoRepository();
var photos = pr.GetAll();
AutoMapperRegistry.Configure();
foreach (var p in photos)
{
var photo = Mapper.Map<Photo, PhotoViewModel>(p);
Console.WriteLine("Photographer: " + photo.PhotographerName);
}
Console.Read();
var p1 = new Photo();
p1.Id = Guid.NewGuid();
p1.Name = "Test Photo";
p1.Photographer.Id = Guid.NewGuid();
p1.Photographer.Name = "John Smith";
p1.DateTaken = DateTime.Now;
pr.Save(p1);
}
Download Source Here
Hopefully Jimmy reads this post and lets me know if there is anything messed up or anything that I'm not doing correctly with my mappings.