I'm new to AutoMapper and i have the following manual mapping in CustomerService in Service Layer in my application, where i tried to find out the equivalent AutoMapper mapping code but i couldn't due to nested and complex objects and collections, so please help me to resolve this issue
here the code from CustomerService : Service.Customer is the DataContract and Data.Customer is the Entity
public Service.Customer GetCustomer(string customerID)
{
Data.Customer customer
= _northwindEntities
.Customers.Single(
c => c.CustomerID == customerID);
return new Service.Customer
{
CustomerID = customer.CustomerID,
CompanyName = customer.CompanyName,
ContactName = customer.ContactName,
Address = customer.Address,
City = customer.City,
Country = customer.Country,
Region = customer.Region,
PostalCode = customer.PostalCode,
Phone = customer.Phone,
Orders
= GetOrders(customer.Orders)
};
}
Service.Order is the DataContract and Data.Order is the Entity ...
private static IEnumerable<Service.Order> GetOrders(
IEnumerable<Data.Order> order)
{
return order.Select(o => new Service.Order
{
OrderID = o.OrderID,
OrderDate = o.OrderDate,
OrderDetails = GetOrderDetails(o),
Freight = o.Freight,
ShippedDate = o.ShippedDate
}).ToList();
}
Service.OrderDetail is the DataContract and Data.Order is the Entity ...
private static IEnumerable<Service.OrderDetail> GetOrderDetails(
Data.Order order)
{
return order.Order_Details.Select(
o => new Service.OrderDetail
{
Product
= new Service.Product
{
ProductID
= o.Product.ProductID,
ProductName
= o.Product.ProductName
},
Quantity = o.Quantity,
UnitPrice = o.UnitPrice
}).ToList();
}
So OrderDetails are nested inside Oreders and Orders are nested inside Customer ...How to reflect this hierarchy using AutoMapper
Thanks in advance
You need to define mappings for the Parent class and all the nested classes, you can then customize them as per your requirements
Mapper.CreateMap<Data.Customer, Service.Customer>();
Mapper.CreateMap<Data.Order, Service.Order>();
Mapper.CreateMap<Data.OrderDetails, Service.OrderDetails>();
Mapper.CreateMap<Data.Product, Service.Product>();
Have a look at this
http://automapper.codeplex.com/wikipage?title=Nested%20Mappings
Related
I'm working with MVC and WCF Service.My MVC Project and WCF Service in same solution.I have same customer classes in mvc project and wcf service project.
I write a method in service return List<Customer> and I want to call this method in mvc project but I have an error like "Cannot implicity convert type <x.Customer> to <y.Customer> ".
Anyway I change service reference configuration like Generic.List but I have same error. How can I fix the problem?
public class ReportService : IReportService
{
protected static List<Customer> Customers;
public List<Customer> GetReport(string Name,string Surname,string Address,string Phone) {
//NHibernate üzerinden select
Customers = new List<Customer>();
using (var session = NHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var results = from c in session.Query<Customer>()
select c;
foreach (var result in results)
{
Customer customer = new Customer
{
CustomerId = result.CustomerId,
Name = result.Name,
Surname = result.Surname,
Address = result.Address,
Phone = result.Phone
};
Customers.Add(customer);
}
if (Customers.Count>0)
{
return Customers;
}
else
{
return null;
}
}
}
}
MVC code:
ServiceReport.ReportServiceClient service = new ServiceReport.ReportServiceClient();
List<Customer> list = new List<Customer>();
list = service.GetReport(Name, Surname, Address, Phone);
I need an nhibernate query to get the quantity count .
here's my entities. I have a master Inventory table and a Used Inventory table.
public Inventory
{
Id,
Name,
Type,
...
}
public UsedInventory
{
Id,
Inventory,
Quantity,
Date,
..
}
I am looking for output that look like:
public ResultDTO
{
Inventory,
TotalUsedQuantity
}
please help.
Thanks
In LINQ, it is easy:
session.Query<UsedInventory>().GroupBy(x => x.Inventory).Select(x => new ResultDTO { Inventory = x.Key, TotalUsedQuantity = x.Count() }).ToList();
In QueryOver:
ResultDTO dto = null;
var rrr = session.QueryOver<UsedInventory>().SelectList(list => list
.SelectGroup(m => m.Inventory).WithAlias(() => dto.Inventory)
.SelectCount(m => m.Id).WithAlias(() => dto.TotalUsedQuantity)).List<ResultDTO>();
Background
I'm attempting to use ServiceStack.OrmLite to grab some values (so I can cache them to run some processing against them).
I need to grab a combination of three values, and I have a custom SQL statement that will yield them (does the joins, etc.)
Because this will be a large list of combinations, I'd like to pass in some lists of values and use Sql.In to filter to only the results that have those values.
Specifics
I need to check whether an invoice is unique to a firm and another value (called ClaimLawsuitID here).
so have my poco:
public class FirmIDClaimLawsuitIDInvoiceNumberCombination
{
public string FirmID { get; set; }
public string ClaimLawsuitID { get; set; }
public string InvoiceNumber { get; set; }
}
and I have my SQL statement:
select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)
I would like to run the following:
public List<FirmIDClaimLawsuitIDInvoiceNumberCombination> GetFirmIDClaimLawsuitIDInvoiceNumberCombinationsForExistingItems(IEnumerable<int> firmIds, IEnumerable<long> claimLawsuitIDs, IEnumerable<string> invoiceNumbers)
{
var sql = #"select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)";
var ev = OrmLiteConfig.DialectProvider.ExpressionVisitor<tblClaimLawsuit>();
var firmFilter = PredicateBuilder.True<tblDefenseInvoice>();
var claimLawsuitFilter = PredicateBuilder.True<tblDefInvClaimantDetail>();
var invoiceNumberFilter = PredicateBuilder.True<tblDefInvClaimantDetail>();
firmFilter = x => Sql.In(x.FirmID, firmIds);
claimLawsuitFilter = x => Sql.In(x.ClaimLawsuitID, claimLawsuitIDs);
invoiceNumberFilter = x => Sql.In(x.InvoiceNumber, invoiceNumbers);
ev.Select(sql);
ev.Where(firmFilter);
ev.Where(claimLawsuitFilter);
ev.Where(invoiceNumberFilter);
return dal.DB.Select<FirmIDClaimLawsuitIDInvoiceNumberCombination>(ev.ToSelectStatement());
}
Question
Is this possible to achieve this way?
Is there some other way of achieving this within ServiceStack's OrmLite that is cleaner and I'm unaware of?
Since I was selecting to a POCO, I simply needed to add the filters based on that POCO.
The following worked just fine:
public List<FirmIDClaimLawsuitIDInvoiceNumberCombination>
GetFirmIDClaimLawsuitIDInvoiceNumberCombinationsForExistingItems(
IEnumerable<long> firmIds,
IEnumerable<long> claimLawsuitIDs)
{
var sql = #"select tblDefenseInvoice.FirmID, tblDefInvClaimantDetail.ClaimLawsuitID, tblDefInvClaimantDetail.invoiceNumber
from tblDefenseInvoice
inner join tblDefInvClaimantDetail
on(tblDefenseInvoice.DefenseInvoiceID = tblDefInvClaimantDetail.DefenseInvoiceID)";
var ev = OrmLiteConfig.DialectProvider.ExpressionVisitor<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
var firmFilter = PredicateBuilder.True<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
var claimLawsuitFilter = PredicateBuilder.True<FirmIDClaimLawsuitIDInvoiceNumberCombination>();
firmFilter = x => Sql.In(x.FirmID, firmIds);
claimLawsuitFilter = x => Sql.In(x.ClaimLawsuitID, claimLawsuitIDs);
ev.Select(sql);
ev.Where(firmFilter);
ev.Where(claimLawsuitFilter);
return dal.DB.Select<FirmIDClaimLawsuitIDInvoiceNumberCombination>(ev.ToSelectStatement());
}
Using Active Record/NHibernate, I'm trying to select an entity (Site) which has multiple child collections.
There is only one Site with the given siteId, yet the FindAll returns the Site 28 times; it's being duplicated due to the child collections that it's loading. How do I get it to load just the 1 Site and arrays of the child collections? I don't mind if it does 5 selects, one to grab the site and then 1 per child collection.
Here is the code:
var criteria = DetachedCriteria.For<Site>()
.CreateAlias("TimeZone", "tz", NHibernate.SqlCommand.JoinType.InnerJoin)
.CreateAlias("Logos", "l", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.CreateAlias("SiteColors", "sc", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.CreateAlias("ManagerUsers", "mu", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Add(Restrictions.Eq("Id", siteId));
var sites = FindAll(criteria);
I should mention that I also tried an hql approach using fetch, however fetch is not fetching! It returns only the one Site (good) but none of the child collections are eagerly loaded (bad).
public static Site Get(int id)
{
var query = new SimpleQuery<Site>(#"
from Site s
where s.Id = ?
inner join fetch s.TimeZone tc
left join fetch s.Logos l
left join fetch s.SiteColors sc
left join fetch s.ManagerUsers mu
", id);
var results = query.Execute().ToList();
return results.FirstOrDefault();
}
Here is code that seems to work, using the "Future" approach:
public static Site Get(int id)
{
var session = ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(Site));
var query = session.CreateQuery("from Site s left join fetch s.Logos where s.Id = :id").SetParameter("id", id).Future<Site>();
session.CreateQuery("from Site s left join fetch s.SiteColors where s.Id = :id2").SetParameter("id2", id).Future<Site>();
session.CreateQuery("from Site s left join fetch s.ManagerUsers where s.Id = :id3").SetParameter("id3", id).Future<Site>();
return query.FirstOrDefault();
}
All of my data model classes inherit from a SimpleModel class, which I've added Equals and GetHashCode methods to:
public abstract class SimpleModel
{
protected SimpleModel()
{
DateCreated = DateTimeAccess.Now;
}
[PrimaryKey]
[DocumentId]
public virtual int Id { get; set; }
[Property]
public virtual DateTime DateCreated { get; set; }
public override bool Equals(object obj)
{
if (obj is SimpleModel)
{
return Id.Equals(((SimpleModel)obj).Id);
}
else
{
return false;
}
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
Call SetResultTransformer(DistinctRootEntity) on your criteria. It will collapse those duplicate Site instances to a single instance.
For more information, see this thread: http://groups.google.com/group/nhusers/browse_thread/thread/9919812230702ccc
SQL query:
SELECT ArticleCategories.Title AS Category, Articles.Title, Articles.[Content], Articles.Date
FROM ArticleCategories INNER JOIN
Articles ON ArticleCategories.CategoryID = Articles.CategoryID
Object repository:
public class ArticleDisplay
{
public int CategoryID;
public string CategoryTitle;
public int ArticleID;
public string ArticleTitle;
//public string ArticleDate;
public string ArticleContent;
}
public class ArticleRepository
{
private DB db = new DB();
//
// Query Methods
public IQueryable<ArticleDisplay> FindAllArticles()
{
var result = from category in db.ArticleCategories
join article in db.Articles on category.CategoryID equals article.CategoryID
select new
{
CategoryID = category.CategoryID,
CategoryTitle = category.Title,
ArticleID = article.ArticleID,
ArticleTitle = article.Title,
//ArticleDate = article.Date,
ArticleContent = article.Content
};
return result;
}
....
}
And finally, I get this error:
Error 1 Cannot implicitly convert type
'System.Linq.IQueryable'
to
'System.Linq.IQueryable'.
An explicit conversion exists (are you
missing a cast?) C:\Documents and
Settings\ilija\My Documents\Visual
Studio
2008\Projects\CMS\CMS\Models\ArticleRepository.cs 29 20 CMS
Any idea what did I do wrong?
Thanks,
Ile
Your method has a return type of IQueryable<Article>, but your LINQ query is not returning articles. Instead it's trying to return an anonymous type made up of properties from both category and article. You could create a class to hold this combination of properties and change the method signature to use that class.
As Adam said, if you're not wanting to return the full article class then you'll need to return your own class.
public IQueryable<ArticleDisplay> FindAllArticles()
{
var result = from category in db.ArticleCategories
join article in db.Articles on category.CategoryID equals article.CategoryID
select new ArticleDisplay() //specify your new class
{
CategoryID = category.CategoryID,
CategoryTitle = category.Title,
....
};
return result;
}
Your updated code still returns an anonymous class....