I am creating a project that uses Entity framework Database first approach. The .edmx is currently generated and is in my data access layer project.
I have created a function import call GetAllTeam and corresponding complex type call TeamResult. I am trying to return the data to business layer by calling my function import, populating the complex type in the data access layer.
In my business layer I shall then map the complex type to business object and return to my web api. I would like to know if my approach is correct. Do I need to create a separate class project called entities with a class called team and then AutoMap that class with TeamResult the complex type and then return to the business layer or is it fine directly sending the TeamResult to the business layer.
Let me also know if there is any other issue with this approach.
Please see the code below
Data access layer:
public class TeamRepository
{
public IEnumerable<TeamResult> GetAllTeam()
{
using (var mcrContext = new MCREntities1())
{
return (from team in mcrContext.GetAllTeam()
select new TeamResult
{
TeamName = team.TeamName,
TeamDescription = team.TeamDescription,
Code = team.Code
}).ToList();
}
}
}
Business logic layer:
public class TeamService : ITeamService
{
private readonly ITeamRepository _teamRepository;
public TeamService(ITeamRepository teamRepository)
{
_teamRepository = teamRepository;
}
public IEnumerable<TeamDto> GetTeam()
{
IEnumerable<TeamResult> team = _teamRepository.GetAllTeam();
if (team != null)
{
foreach (var t in team)
{
yield return Mapper.Map<TeamDto>(t);
}
}
yield break;
}
}
public class DomainToDtoMapping : Profile
{
public DomainToDtoMapping()
{
CreateMap<TeamResult, TeamDto>().ReverseMap();
}
public override string ProfileName
{
get { return "DomainToDtoMapping"; }
}
}
Web Api:
public class TeamController : ApiController
{
private readonly ITeamService _teamServices;
public TeamController(ITeamService _teamServices)
{
_teamServices = teamServices;
}
public HttpResponseMessage Get()
{
var teams = _teamServices.GetTeam();
if (teams != null)
{
var teamEntities = teams as List<TeamDto> ?? teams.ToList();
if (teamEntities.Any())
return Request.CreateResponse(HttpStatusCode.OK, teamEntities);
}
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Team not found");
}
}
Personally, I think you are doing this just fine. Having another entity to map the stored procedure to before returning it from the repository wouldn't add any value because you are returning exactly what the stored procedure exposes already.
The business layer needs to know about any entities that the Repository can return and then map it to something to return later. This all looks good to me! :)
Related
I'm using Dapper Extensions and have defined my own custom mapper to deal with entities with composite keys.
public class MyClassMapper<T> : ClassMapper<T> where T : class
{
public MyClassMapper()
{
// Manage unmappable attributes
IList<PropertyInfo> toIgnore = typeof(T).GetProperties().Where(x => !x.CanWrite).ToList();
foreach (PropertyInfo propertyInfo in toIgnore.ToList())
{
Map(propertyInfo).Ignore();
}
// Manage keys
IList<PropertyInfo> propsWithId = typeof(T).GetProperties().Where(x => x.Name.EndsWith("Id") || x.Name.EndsWith("ID")).ToList();
PropertyInfo primaryKey = propsWithId.FirstOrDefault(x => string.Equals(x.Name, $"{nameof(T)}Id", StringComparison.CurrentCultureIgnoreCase));
if (primaryKey != null && primaryKey.PropertyType == typeof(int))
{
Map(primaryKey).Key(KeyType.Identity);
}
else if (propsWithId.Any())
{
foreach (PropertyInfo prop in propsWithId)
{
Map(prop).Key(KeyType.Assigned);
}
}
AutoMap();
}
}
I also have this test case to test my mapper:
[Test]
public void TestMyAutoMapper()
{
DapperExtensions.DapperExtensions.DefaultMapper = typeof(MyClassMapper<>);
MySubscribtionEntityWithCompositeKey entity = new MySubscribtionEntityWithCompositeKey
{
SubscriptionID = 145,
CustomerPackageID = 32
};
using (var connection = new SqlConnection(CONNECTION_STRING))
{
connection.Open();
var result = connection.Insert(entity);
var key1 = result.SubscriptionID;
var key2 = result.CustomerPackageID;
}
}
Note that I set the default mapper in the test case.
The insert fails and I notive that my customer mapper is never called. I have no documentation on the github page on the topic, so I'm not sure if there's anything else I need to do to make dapper extensions use my mapper.
Thanks in advance!
Looking at your question, you are attempting to write your own defalut class mapper derived from the existing one. I never used this approach; so I do not know why it is not working or whether it should work.
I explicitly map the classes as below:
public class Customer
{
public int CustomerID { get; set; }
public string Name { get; set; }
}
public sealed class CustomerMapper : ClassMapper<Customer>
{
public CustomerMapper()
{
Schema("dbo");
Table("Customer");
Map(x => x.CustomerID).Key(KeyType.Identity);
AutoMap();
}
}
The AutoMap() will map rest of the properties based on conventions. Please refer to these two resources for more information about mapping.
Then I call SetMappingAssemblies at the startup of the project as below:
DapperExtensions.DapperExtensions.SetMappingAssemblies(new[] { Assembly.GetExecutingAssembly() });
The GetExecutingAssembly() is used in above code because mapping classes (CustomerMapper and other) are in same assembly which is executing. If those classes are placed in other assembly, provide that assembly instead.
And that's it, it works.
To set the dialect, I call following line just below the SetMappingAssemblies:
DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqlServerDialect();
Use your preferred dialect instead of SqlServerDialect.
Apparently, the solution mentioned here may help you achieve what you are actually trying to. But, I cannot be sure, as I said above, I never used it.
Let's say you have an order as an aggregate root. An order contains one or more line items.
It is my understanding that it's the repository's responsibility to instantiate an order object when asked.
The line items can be loaded at the time of the order object's creation (eager loaded), or the line item collection can be populated when it is accessed by the client code (lazy loaded).
If we are using eager loading, it's seems that the repository code would take responsibility with hydrating the line items when the order is created.
However if we are using lazy loading, how is the repository called when the LineItems collection is accessed without creating a dependency on the repository from the order domain class?
Main problem is in Repository's ability to get only aggregate roots (presenting aggregates), thus you cannot use Repository to get line items. This can lead to aggregate encapsulation violation.
I propose something like:
//Domain level:
public interface IOrderItemList {
IEnumerable<OrderItem> GetItems();
}
public class Order {
private IOrderItemList _orderItems;
public IEnumerable<OrderItem> OrderItems
{ get { return _orderItems.GetItems() } };
public Order(IOrderItemList orderItems)
{
_orderItems = orderItems;
}
}
public class OrderItemList : IOrderItemList
{
private IList<OrderItem> _orderItems;
public IEnumerable<OrderItem> GetItems() {
return _orderItems; //or another logic
}
//other implementation details
}
//Data level
public class OrderItemListProxy : IOrderItemList
{
//link to 'real' object
private OrderItemList _orderItemList;
private int _orderId;
//alternatively:
//private OrderEntity _orderEntity;
//ORM context
private DbContext _context;
public OrderItemListProxy(int orderId, DbContext context)
{
_orderId = orderId;
_context = context;
}
public IEnumerable<OrderItem> GetItems() {
if (_orderItemList == null)
{
var orderItemEntities = DbContext.Orders
.Single(order => order.Id == _orderId).OrderItems;
var orderItems = orderItemEntites.Select(...);
//alternatively: use factory to create OrderItem from OrderItemEntity
_orderItemList = new OrderItemList(orderItems);
}
return _orderItemList.GetItems();
}
}
public class OrderRepository
{
//ORM context
private DbContext _context;
Order GetOrder(int id)
{
var orderEntity = _context.Single(order => order.Id == id);
var order = new Order(new OrderItemListProxy(id, _context))
//alternatively:
//var order = new Order(new OrderItemListProxy(orderEntity, _context))
...
//init other fields
...
}
//other methods
...
}
Most important here is that IOrderItemList corresponds to domain layer, but OrderItemListProxy corresponds to data layer.
Finally,
You may use IList<OrderItem> instead of custom IOrderItemList or another appropriate interface.
Proxy implementation may differ.
I don't provide best practicies for using db context, it may depend on technologies you use.
I am creating a rule set engine that looks kinda like a unit test framework.
[RuleSet(ContextA)]
public class RuleSet1
{
[Rule(TargetingA)]
public Conclusion Rule1(SubjectA subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
[RuleSet(ContextB)]
public class RuleSet2
{
[Rule(TargetingB)]
public Conclusion Rule1(SubjectB subject)
{ Create conclusion }
[Rule(TargetingA)]
public Conclusion Rule2(SubjectA subject)
{ Create conclusion }
[Rule(TargetingB)]
public Conclusion Rule3(SubjectB subject)
{ Create conclusion }
}
public class Conclusion()
{
// Errorcode, Description and such
}
// contexts and targeting info are enums.
The goal is to create an extensible ruleset that doesn't alter the API from consumer POV while having good separation-of-concerns within the code files. Again: like a unit test framework.
I am trying to create a library of these that expose the following API
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets(contextFlags contexts)
{
{
return from type in Assembly.GetExecutingAssembly().GetTypes()
let attribute =
type.GetCustomAttributes(typeof (RuleSetAttribute), true)
.OfType<RuleSetAttribute>()
.FirstOrDefault()
where attribute != null
select ?? I don't know how to convert the individual methods to Func's.
}
}
}
internal interface IRuleset
{
IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; }
IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; }
}
...which allows consumers to simply use like this (using foreach instead of LINQ for readability in this example)
foreach (var ruleset in RuleEgine.RuleSets(context))
{
foreach (var rule in ruleset.SubjectARules)
{
var conclusion = rule(myContextA);
//handle the conclusion
}
}
Also, it would be very helpful if you could tell me how to get rid of "TargetingA" and "TargetingB" as RuleAttribute parameters and instead use reflection to inspect the parameter type of the decorated method directly. All the while maintaining the same simple external API.
You can use Delegate.CreateDelegate and the GetParameters method to do what you want.
public class RuleSet : IRuleSet
{
public IEnumerable<Func<SubjectA, Conclusion>> SubjectARules { get; set; }
public IEnumerable<Func<SubjectB, Conclusion>> SubjectBRules { get; set; }
}
public static class RuleEngine
{
public static IEnumerable<IRuleSet> RuleSets() // removed contexts parameter for brevity
{
var result = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes(typeof(RuleSetAttribute), true).Any()
let m = t.GetMethods().Where(m => m.GetCustomAttributes(typeof(RuleAttribute)).Any()).ToArray()
select new RuleSet
{
SubjectARules = CreateFuncs<SubjectA>(m).ToList(),
SubjectBRules = CreateFuncs<SubjectB>(m).ToList()
};
return result;
}
}
// no error checking for brevity
// TODO: use better variable names
public static IEnumerable<Func<T, Conclusion>> CreateFuncs<T>(MethodInfo[] m)
{
return from x in m
where x.GetParameters()[0].ParameterType == typeof(T)
select (Func<T, Conclusion>)Delegate.CreateDelegate(typeof(Func<T, Conclusion>), null, x);
}
Then you can use it like this:
var sa = new SubjectA();
foreach (var ruleset in RuleEngine.RuleSets())
{
foreach (var rule in ruleset.SubjectARules)
{
var conclusion = rule(sa);
// do something with conclusion
}
}
In your LINQ query you headed straight for RuleSetAttribute, and so lost other information. If you break the query in several lines of code you can get methods from the type with GetMethods(), and then you can call GetCustomAttribute<RuleAttribute>().
My current implementation for service and business layer is straight forward as below.
public class MyEntity { }
// Business layer
public interface IBusiness { IList<MyEntity> GetEntities(); }
public class MyBusinessOne : IBusiness
{
public IList<MyEntity> GetEntities()
{
return new List<MyEntity>();
}
}
//factory
public static class Factory
{
public static T Create<T>() where T : class
{
return new MyBusinessOne() as T; // returns instance based on T
}
}
//Service layer
public class MyService
{
public IList<MyEntity> GetEntities()
{
return Factory.Create<IBusiness>().GetEntities();
}
}
We needed some changes in current implementation. Reason being data grew over the time and service & client cannot handle the volume of data. we needed to implement pagination to the current service. We also expect some more features (like return fault when data is more that threshold, apply filters etc), so the design needs to be updated.
Following is my new proposal.
public interface IBusiness
{
IList<MyEntity> GetEntities();
}
public interface IBehavior
{
IEnumerable<T> Apply<T>(IEnumerable<T> data);
}
public abstract class MyBusiness
{
protected List<IBehavior> Behaviors = new List<IBehavior>();
public void AddBehavior(IBehavior behavior)
{
Behaviors.Add(behavior);
}
}
public class PaginationBehavior : IBehavior
{
public int PageSize = 10;
public int PageNumber = 2;
public IEnumerable<T> Apply<T>(IEnumerable<T> data)
{
//apply behavior here
return data
.Skip(PageNumber * PageSize)
.Take(PageSize);
}
}
public class MyEntity { }
public class MyBusinessOne : MyBusiness, IBusiness
{
public IList<MyEntity> GetEntities()
{
IEnumerable<MyEntity> result = new List<MyEntity>();
this.Behaviors.ForEach(rs =>
{
result = rs.Apply<MyEntity>(result);
});
return result.ToList();
}
}
public static class Factory
{
public static T Create<T>(List<IBehavior> behaviors) where T : class
{
// returns instance based on T
var instance = new MyBusinessOne();
behaviors.ForEach(rs => instance.AddBehavior(rs));
return instance as T;
}
}
public class MyService
{
public IList<MyEntity> GetEntities(int currentPage)
{
List<IBehavior> behaviors = new List<IBehavior>() {
new PaginationBehavior() { PageNumber = currentPage, }
};
return Factory.Create<IBusiness>(behaviors).GetEntities();
}
}
Experts please suggest me if my implementation is correct or I am over killing it. If it correct what design pattern it is - Decorator or Visitor.
Also my service returns JSON string. How can I use this behavior collections to serialize only selected properties rather than entire entity. List of properties comes from user as request. (Kind of column picker)
Looks like I don't have enough points to comment on your question. So, I am gonna make some assumption as I am not a C# expert.
Assumption 1: Looks like you are getting the data first and then applying the pagination using behavior object. If so, this is a wrong approach. Lets say there are 500 records and you are showing 50 records per fetch. Instead of simply fetching 50 records from DB, you are fetching 500 records for 10 times and on top of it you are adding a costly filter. DB is better equipped to do this job that C# or Java.
I would not consider pagination as a behavior with respect to the service. Its the behavior of the presentation layer. Your service should only worry about 'Data Granularity'. Looks like one of your customer wants all the data in one go and others might want a subset of that data.
Option 1: In DAO layer, have two methods: one for pagination and other for regular fetch. Based on the incoming params decide which method to call.
Option 2: Create two methods at service level. One for a small subset of data and the other for the whole set of data. Since you said JSON, this should be Restful service. Then based on the incoming URL, properly call the correct method. If you use Jersey, this should be easy.
In a service, new behaviors can be added by simply exposing new methods or adding new params to existing methods/functionalities (just make sure those changes are backward compatible). We really don't need Decorator or Visitor pattern. The only concern is no existing user should be affected.
Consider the following existing classes which uses MEF to compose Consumer.
public interface IProducer
{
void Produce();
}
[Export(typeof(IProducer))]
public class Producer : IProducer
{
public Producer()
{
// perform some initialization
}
public void Produce()
{
// produce something
}
}
public class Consumer
{
[Import]
public IProducer Producer
{
get;
set;
}
[ImportingConstructor]
public Consumer(IProducer producer)
{
Producer = producer;
}
public void DoSomething()
{
// do something
Producer.Produce();
}
}
However, the creation of Producer has become complex enough that it can no longer be done within the constructor and the default behavior no longer suffices.
I'd like to introduce a factory and register it using a custom FactoryAttribute on the producer itself. This is what I have in mind:
[Export(typeof(IProducer))]
[Factory(typeof(ProducerFactory))]
public class Producer : IProducer
{
public Producer()
{
// perform some initialization
}
public void Produce()
{
// produce something
}
}
[Export]
public class ProducerFactory
{
public Producer Create()
{
// Perform complex initialization
return new Producer();
}
}
public class FactoryAttribute : Attribute
{
public Type ObjectType
{
get;
private set;
}
public FactoryAttribute(Type objectType)
{
ObjectType = objectType;
}
}
If I had to write the "new" code myself, it may very well look as follows. It would use the factory attribute, if it exists, to create a part, or default to the MEF to create it.
public object Create(Type partType, CompositionContainer container)
{
var attribute = (FactoryAttribute)partType.GetCustomAttributes(typeof (FactoryAttribute), true).FirstOrDefault();
if (attribute == null)
{
var result = container.GetExports(partType, null, null).First();
return result.Value;
}
else
{
var factoryExport = container.GetExports(attribute.ObjectType, null, null).First();
var factory = factoryExport.Value;
var method = factory.GetType().GetMethod("Create");
var result = method.Invoke(factory, new object[0]);
container.ComposeParts(result);
return result;
}
}
There are a number of articles how to implement a ExportProvider, including:
MEF + Object Factories using Export Provider
Dynamic Instantiation
However, the examples are not ideal when
The application has no dependencies or knowledge of Producer, only IProducer. It would not be able to register the factory when the CompositionContainer is created.
Producer is reused by several applications and a developer may mistakenly forget to register the factory when the CompositionContainer is created.
There are a large number of types that require custom factories and it may pose a maintenance nightmare to remember to register factories when the CompositionContainer is created.
I started to create a ExportProvider (assuming this would provide the means to implement construction using factory).
public class FactoryExportProvider : ExportProvider
{
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition,
AtomicComposition atomicComposition)
{
// What to do here?
}
}
However, I'm having trouble understanding how to tell MEF to use the factory objects defined in the FactoryAttribute, and use the default creation mechanism if no such attribute exists.
What is the correct manner to implement this? I'm using MEF 2 Preview 5 and .NET 4.
You can make use of a property export:
public class ProducerExporter
{
[Export]
public IProducer MyProducer
{
get
{
var producer = new Producer();
// complex initialization here
return producer;
}
}
}
Note that the term factory isn't really appropriate for your example, I would reserve that term for the case where the importer wants to create instances at will, possibly by providing one or more parameters. That could be done with a method export:
public class ProducerFactory
{
[Export(typeof(Func<Type1,Type2,IProducer>)]
public IProducer CreateProducer(Type1 arg1, Type2 arg2)
{
return new Producer(arg1, arg2);
}
}
On the import side, you would then import a Func<Type1,Type2,IProducer> that you can invoke at will to create new instances.