I have the following code that is layered as below:
Data - DbContext database access.
Entities - POCO entities with INotifyPropertyChanged
WCF Service - Uses Data and Entities
Test Library
Here is the code from test method.
SalesOrder order = new SalesOrder();
order.CustomerID = 1;
order.OrderDate = DateTime.Now;
order.SalesTax = 5.60M;
order.ShipCharge = 5.00M;
order.DiscountPercent = 20;
order.ModifiedByUser = Environment.UserName;
order.CreatedByUser = Environment.UserName;
SalesOrderDetail detail = new SalesOrderDetail();
detail.SalesOrder = order;
detail.OrderID = order.OrderID;
detail.OrderQuantity = 15;
detail.UnitPrice = 20;
detail.Description = "Test";
detail.ModifiedByUser = Environment.UserName;
detail.CreatedByUser = Environment.UserName;
order.SalesOrderDetails.Add(detail);
order = _service.SaveOrder(order);
order.SalesOrderDetails has one item at this time. But when it reaches the WCF method, order.SalesOrderDetails has a count of 0.
Here is my SalesOrder class and SalesOrderDetail class
public partial class SalesOrder: EntityBase
{
public SalesOrder()
{
this.SalesOrderDetails = new BindingList<SalesOrderDetail>();
((BindingList<SalesOrderDetail>)SalesOrderDetails).ListChanged += SalesOrder_ListChanged;
}
.... other properties
[DataMember]
public ICollection SalesOrderDetail{get; set;}
}
public partial class SalesOrderDetail : EntityBase
{
.... other properties
[DataMember]
public SalesOrder SalesOrder{get; set;}
}
My EntityBase
[DataContract(IsReference = true)]
public class EntityBase:IAuditable, INotifyPropertyChanged
{
.... IAuditable, INotify members
}
My WCF Method
public SalesOrder SaveOrder(SalesOrder order) // At this point order.SalesOrderDetails count is 0.
{
if (order.OrderID == 0)
AddSalesOrder(order);
else
UpdateSalesOrder(order);
return order;
}
What am I missing here? Thanks for your help!
I fixed it by adding [DataContract(IsReference = true)] to public partial class SalesOrder: EntityBase and public partial class SalesOrderDetail : EntityBase. Not sure how it made a difference. But that fixed my issue.
Related
I have a Web Api Application where I have EF DB first entities and DTO classes.
So this is my generic repository interface -
public interface IRepository<TEntity> where TEntity:class
{
IQueryable<TEntity> GetAll();
void Create(TEntity Entity);
TEntity GetById(int id);
void Update(TEntity Entity);
void Remove(int id);
}
Here is a sample of the GetAll method implementation for one of the services -
public class OrdersRepository : IRepository<SalesOrderHeader>
{
private AdventureWorksEntities db = new AdventureWorksEntities();
public IQueryable<SalesOrderHeader> GetAll()
{
return db.SalesOrderHeaders;
}
And here is my service or apicontroller calling the method along with additional mapping -
public IQueryable<Orders> GetSalesOrderHeaders()
{
**var Orders = orderRepo.GetAll();**
var OrderDetails = orderDetailRepo.GetAll();
return (from so in Orders
select new Orders()
{
SalesOrderID = so.SalesOrderID,
SalesOrderNumber = so.SalesOrderNumber,
ShipDate = so.ShipDate.ToString(),
Customer = customerRepo.GetById(so.CustomerID),
OrderItems = (from sod in OrderDetails
select new OrderItems()
{
SalesOrderId = sod.SalesOrderID,
ProductID = sod.ProductID,
Quantity = sod.OrderQty,
UnitPrice = sod.UnitPrice
}).Where(a => a.SalesOrderId == so.SalesOrderID).ToList()
});
}
As seen here the mapping is being done here in the apicontroller class. Similarly for Create/Add method of repository, where will this happen? If in the apicontroller, does that mean I need access to Entity in my apicontroller? if in the Repository, then i will have to map the DTO to Entity in my repository. Both seem dubious. Here is my DTO class -
public class Orders
{
public int SalesOrderID { get; set; }
public string SalesOrderNumber { get; set; }
public string ShipDate { get; set; }
public CustomerDTO Customer { get; set; }
public List<OrderItems> OrderItems { get; set; }
}
The entity class is called SalesOrderHeaders and has a lot more fields.
Neither. Like you, I faced this dilemma with my code and decided that implementing object mapping in aither the controller or the repository will only add innecesary complexity and will end up violating the DRY (Don't Repeat Yourself) principle, and since using an ORM was overkill for the size of the project, I end up creating a set of extension methods that allowed me do the job in a clean and reusable way.
Here is an example, though incompleted, that may help you build your own:
// File: ModelExtensions.Orders.cs
public static partial class ModelExtensions
{
public static IEnumerable<OrdersDto> MapToDto(this IEnumerable<Orders> list)
{
return list.select(item => item.MapToDto());
}
public static OrdersDto MapToDto(this Orders order)
{
var dto = new OrdersDto() {
SalesOrderID = order.SalesOrderID,
SalesOrderNumber = order.SalesOrderNumber,
ShipDate = order.ShipDate.ToString()
}
}
public static IEnumerable<OrdersDetailsDto> MapToDto(this IEnumerable<OrderDetails> list)
{
return list.select(item => item.MapToDto());
}
public static OrderDetailsDto MapToDto(this OrderDetails orderDetails)
{
var dto = new OrderDetailsDto() {
SalesOrderId = orderDetails.SalesOrderID,
ProductID = orderDetails.ProductID,
Quantity = orderDetails.OrderQty,
UnitPrice = orderDetails.UnitPrice
}
}
}
You can also create similar mapping functions to map from DTOs to Entities.
To use this functions, just include a reference to the namespace where the extension methods are defined, et voila, you have all your mappings at hand.
Basically, the transformation would occur in the API method, since there is where the exchange (DTO/Entity or Entity/DTO) is made.
Using this method, you could use the mapping functions wherever you need it without the need to repeat (DRY principle) the logic in different places.
Sample usage:
public IQueryable<Orders> GetSalesOrderHeaders()
{
var orders = orderRepo.GetAll().MapToDto();
var orderDetails = orderDetailRepo.GetAll();
foreach (var ord in orders)
{
ord.OrderItems = orderDetails.Where(a => a.SalesOrderId == ord.SalesOrderID).MapToDto();
}
return orders.ToList();
}
I have these classes:
class Car {
int ID;
string Name;
}
class Truck : Car {
int MaximumLoad;
}
I have these tables
Car
- ID
- Name
Truck
- CarID
- MaximumLoad
How could I map my classes with my table using PetaPoco ?
If you store Car and Truck in the same table (TPH) you can inherit Truck from Car with minor changes to PetaPOCO source code,
table Vehicle (ID, Discriminator, Name, MaximumLoad)
in PetaPOCO.cs, add
[AttributeUsage(AttributeTargets.Class)]
public class DiscriminatorAttribute : Attribute
{
public int Value { get; private set; }
public DiscriminatorAttribute(object discriminator)
{
Value = (int)discriminator;
}
}
protected bool IsTPHTable<T>()
{
var t = typeof(T);
var a = t.GetCustomAttributes(typeof(DiscriminatorAttribute), true);
return a.Length > 0;
}
protected void AppendDiscriminator<T>(Sql sql)
{
var t = typeof(T);
var a = t.GetCustomAttributes(typeof(DiscriminatorAttribute), true);
sql.Append("Where Discriminator = #0", (a[0] as DiscriminatorAttribute).Value);
}
public IEnumerable<T> Query<T>(Sql sql)
{
if (IsTPHTable<T>())
AppendDiscriminator<T>(sql);
return Query<T>(default(T), sql);
}
// also similar AppendDiscriminator() for Update an Delete.
Then in your Car.cs and Truck.cs, you can write/generate code like this,
public enum VehicleType:int
{
Car,
Truck
}
[TableName("Vehicle")]
[Discriminator(VehicleType.Car)]
public class Car
{
[Column]
public int ID {get; set;}
[Column]
public string Name {get; set;}
public Car()
{
//this.Discriminator = VehicleType.Car;
}
public static new Car SingleOrDefault(object primaryKey) { return repo.SingleOrDefaultById<Car>(primaryKey); }
//...
}
[Discriminator(VehicleType.Truck)]
public class Truck:Car
{
[Column]
public double MaximumLoad {get;set;}
public Truck()
{
//this.Discriminator = VehicleType.Truck;
}
public static new Truck SingleOrDefault(object primaryKey) { return repo.SingleOrDefaultById<Truck>(primaryKey); }
//...
}
To read truck records I would create a Trucks view that combines the two tables. Or have a look at Schotime's muliple result sets :
http://schotime.net/blog/index.php/2011/11/20/petapoco-multiple-result-sets/
For writes I guess you are asking "how can I write to 2 tables in one operation". Off the top of my head I would probably say I would simply perform 2 writes. I think Petapoco will ignore fields that don't map so you may be able to use your truck object for both writes.
Could easily be wrong as I haven't tested this.
I think (have not tested though) that if you do something like this..
repo.Fetch<Truck>(";Select car.*, truck.maximumload from car left join truck on car.id = truck.carid");
or
repo.Fetch<Truck>(";Select car.*, truck.maximumload from car left join truck on car.id = truck.carid where truck.carid = #0", truckid);
I would probably have called my base class vehicle rather than car, buts that's just me.
Hope that helps ?
Please find below my code. Employee class implements IEmployee interface.
namespace MiddleWare.ServiceContracts
{
[ServiceContract(Namespace = "http://mywebsite.com/MyProject")]
public interface IMiscellaneous
{
[OperationContract]
[ServiceKnownType(typeof(MiddleWare.Classes.Employee))]
IEnumerable<IEmployee> Search_Employee
(string SearchText);
}
namespace MiddleWare.ServiceClasses
{
public class Miscellaneous : IMiscellaneous
{
public IEnumerable<IEmployee> Search_Employee
(string SearchText)
{
List<IEmployee> emp = new List<IEmployee>();
IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(IEmployee));
TempObject.EmployeeId = "12345678";
emp.Add(TempObject);
return emp;
}
}
}
As is visible the above code does compile but wont work because interface instance cannot be created.How can I achive DI(Dependency Injection) here...If I write..
IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(Employee));
Then this class will be dependent not only on the Interface but also the class...assuming that one fine day Employee class becomes Employee2.There will be code changes at two places..
1)[ServiceKnownType(typeof(MiddleWare.Classes.Employee2))]
2)IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(Employee2));
I want to avoid that. Can we do something at implementation of IOperationBehavior or is there a Ninject way of achieving this or am I trying to achieve impossible?
Consider a design change - Use the factory pattern to create an instance of your employee.
public EmployeeFactory : IEmployeeFactory
{
public IEmployee CreateEmployee()
{
return new Employee();
}
}
And introduce a dependency on the Factory from your middleware, so creating a new IEmployee becomes:
public class Miscellaneous : IMiscellaneous
{
private readonly IEmployeeFasctory _employeeFactory;
public class Miscellaneous(IEmployeeFactory employeeFactory)
{
_employeeFactory = employeeFactory;
}
public IEnumerable Search_Employee (string searchText)
{
List employees = new List();
IEmployee employee = _employeeFactory.CreateEmployee();
employee.EmployeeId = "12345678";
employees.Add(TempObject);
return employees;
}
And then you can inject your EmployeeFactory into Miscellaneous. And should Employee one day become deprecated and Employee2 comes along, just change the factory!
As rich.okelly points out in another answer, IEmployeeFactory should be used to create instances of the IEmployee interface, since IEmployee isn't a Service, but an Entity.
The IEmployeeFactory interface, on the other hand, is a Service, so should be injected into the service class using Constructor Injection. Here's a write-up of enabling Constructor Injection in WCF.
Had a discussion within the team.
1) Constructor based implementation is not comfortable..The service would be IIS hosted and consumed as a web-reference.Cannot ask client systems to provide FactoryImplementatedObjects in Miscellaneous class call.
2) Entity based factories is also not absolutely accurate.If I happen to have say 20 specific entities in my project like Employee,Material,Project,Location,Order then I need to have 20 Factories.Also the Miscellaneous class will have several custom constructors to support specific contract calls..
I have prepared a system which is working and DI is achieved to a great level but I feel like I am cheating OOPS..Doesnt feel correct at heart..but cannot be refuted to be wrong..Please check and let me know your comments.
I now have a IEntity Interface which is the base for all other Entities.
namespace BusinessModel.Interfaces
{
public interface IEntity
{
string EntityDescription { get; set; }
}
}
Hence forth all will implement this.
namespace BusinessModel.Interfaces
{
public interface IEmployee : IEntity
{
string EmployeeId { get; set ; }
}
}
namespace BusinessModel.Interfaces
{
public interface IProject : IEntity
{
string ProjectId { get; set; }
}
}
and so on..(Interface implementing interface..absolutely ridiculous,cheating but working)
Next,An Enum type is declared to have a list of all Entities...
namespace MiddleWare.Common
{
internal enum BusinessModel
{
IEmployee,
IProject
}
}
A DI Helper class is created which will henceforth be considered a part of Business Model and any changes to it (Implementation,Naming..) would be taken as a Business Shift.So if DIHelper class has to become DIHelper2 then this is like BIG.(Can this also be avoided??)
namespace MiddleWare.Common
{
internal sealed class DIHelper
{
internal static IEntity GetRequiredIEntityBasedObject(BusinessModel BusinessModelObject)
{
switch (BusinessModelObject)
{
case BusinessModel.IEmployee:
return new Employee();
}
return null;
}
}
}
Function is Self Explanatory...
So now finally,the contract and implementation...
namespace MiddleWare.ServiceContracts
{
[ServiceContract(Namespace = "http://mywebsite.com/MyProject")]
public interface IMiscellaneous
{
[OperationContract]
[ServiceKnownType(typeof(MiddleWare.Classes.Employee))]
IEnumerable<IEmployee> Search_Employee
(string SearchText);
}
}
namespace MiddleWare.ServiceClasses
{
public class Miscellaneous : IMiscellaneous
{
public IEnumerable<IEmployee> Search_Employee
(string SearchText)
{
List<IEmployee> IEmployeeList = new List<IEmployee>();
IEmployee TempObject = (IEmployee)DIHelper.GetRequiredIEntityBasedObject(MiddleWare.Common.BusinessModel.IEmployee);
TempObject.EmployeeId = "12345678";
IEmployeeList.Add(TempObject);
return IEmployeeList;
}
}
}
What do you say??
My Team is happy though :)
From your updated requirements, there is nothing related to DI in this question...
So, to create a type based on the service known types of a service contract you can use:
public class EntityLoader<TServiceContract>
{
private static readonly HashSet<Type> ServiceKnownTypes = new HashSet<Type>();
static EntityLoader()
{
var attributes = typeof(TServiceContract).GetMethods().SelectMany(m => m.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), true)).Cast<ServiceKnownTypeAttribute>();
foreach (var attribute in attributes)
{
ServiceKnownTypes.Add(attribute.Type);
}
}
public TEntity CreateEntity<TEntity>()
{
var runtimeType = ServiceKnownTypes.Single(t => typeof(TEntity).IsAssignableFrom(t));
return (TEntity)Activator.CreateInstance(runtimeType);
}
}
Which is then useable like so:
[ServiceContract(Namespace = "http://mywebsite.com/MyProject")]
public interface IMiscellaneous
{
[OperationContract]
[ServiceKnownType(typeof(Employee))]
IEnumerable<IEmployee> SearchEmployee(string SearchText);
}
public class Miscellaneous : IMiscellaneous
{
private readonly EntityLoader<IMiscellaneous> _entityLoader = new EntityLoader<IMiscellaneous>();
public IEnumerable<IEmployee> SearchEmployee(string SearchText)
{
List<IEmployee> employees = new List<IEmployee>();
IEmployee employee = _entityLoader.CreateEntity<IEmployee>();
employee.EmployeeId = "12345678";
employees.Add(employee);
return employees;
}
}
Obviously, the above code assumes that ALL of your service entities will contain public parameterless constructors and that there will only be one ServiceKnownType that implements each interface.
I'm trying to specify a unique column for an entity, using the Fluent NHibernate Automapper Override. For my test class of CodeType, I'd like to make the Type property unique. The goal would be for a "new CodeType()" being created with the same type field as a currently saved CodeType to be overlaid on top of the current entity.
I have the following CodeType class:
public class CodeType : SecurableEntity
{
public virtual string Type { get; set; }
public virtual string Description { get; set; }
/// <summary>
/// This is a placeholder constructor for NHibernate.
/// A no-argument constructor must be available for NHibernate to create the object.
/// </summary>
public CodeType() { }
}
I have the following CodeTypeMap Class:
public class CodeTypeMap : IAutoMappingOverride<CodeType>
{
public void Override(AutoMapping<CodeType> mapping)
{
//Doesn't work. Need a way to specify a column as unique.
mapping.Map(m => m.Type).Unique();
}
}
The override is applied to the AutoMap, through the following:
public AutoPersistenceModel Generate()
{
var mappings = AutoMap.AssemblyOf<User>(new AutomappingConfiguration());
mappings.IgnoreBase<Entity>();
mappings.IgnoreBase<SecurableEntity>();
mappings.IgnoreBase(typeof(EntityWithTypedId<>));
mappings.Conventions.Setup(GetConventions());
mappings.UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
mappings.UseOverridesFromAssemblyOf<UserMap>();
mappings.UseOverridesFromAssemblyOf<CodeMap>();
mappings.UseOverridesFromAssemblyOf<CodeTypeMap>();
return mappings;
}
I'd like the following code to update any existing record with "type" equal to "existingType".
SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
CodeType ct = new CodeType();
ct.type = "existingType";
ct = ctr.SaveOrUpdate(ct);
How can I make NHibernate key off of the type field as unique?
Is this possible?
short answer, what you want is something you have to handle in code because there are so many possibilities. Everytime you create a new CodeType you have to check the db if there is already one
SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
CodeType ct = ctr.GetByType("existingType");
if (ct == null)
{
ct = new CodeType { type = "existingType" };
}
ctr.SaveOrUpdate(ct);
or
SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
CodeType ct = ctr.GetByType("existingType");
if (ct != null)
{
ctr.Detach(ct);
ctr.Merge(new CodeType{ type = "existingType" });
}
or
SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
int ctId = ctr.GetIdByType("existingType");
if (ct != 0)
{
ctr.Merge(new CodeType{ Id = ctId, type = "existingType" });
}
and there are some things which can be written differently
public CodeType() { } can be removed or made protected CodeType() { } if not needed for your domain
public AutoPersistenceModel Generate()
{
return AutoMap.AssemblyOf<User>(new AutomappingConfiguration())
.IgnoreBase<Entity>()
.IgnoreBase<SecurableEntity>()
.IgnoreBase(typeof(EntityWithTypedId<>))
.Conventions.Setup(GetConventions())
.UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
}
i'm new with wcf and i create a DataContract like this :
[DataContract]
public class directoriesUser
{
[DataMember]
public string NameDir { get; set; }
[DataMember]
public directoriesUser Parent { get; set; }
private ObservableCollection<directoriesUser> _userDirs = new ObservableCollection<directoriesUser>();
[DataMember]
public ObservableCollection<directoriesUser> UserDirectories
{
get { return _userDirs; }
set { _userDirs = value; }
}
}
But whe i use this class like above, the service throw an exception. can someone help me ?
public directoriesUser getHomeUser(int user_id)
{
directoriesUser dirhome = new directoriesUser();
// this doesn't works
dirhome.UserDirectories = new ObservableCollection<directoriesUser>{
new directoriesUser { NameDir = "dir1", Parent = dirhome},
new directoriesUser {NameDir = "dir2", Parent = dirhome}
};
// neither this one
dirhome.UserDirectories.Add(new directoriesUser {NameDir = "dir3", Parent = dirhome})
return dirhome;
}
Your directoriesUser class probably causes recursion when wcf serializes the instance. This is basically caused by the Parent property pointing back up the hierarchy.
Here's a more detailed article about this.