-
Notifications
You must be signed in to change notification settings - Fork 80
Tutorial 1: Step 4: Replacing EntityFramework with CQRS.NET object updates
cdmdotnet edited this page Jun 22, 2017
·
2 revisions
If you missed it, this is the second step, following on from step 3.
- Add a new class for
OrderUpdated
as follows:
// C#
namespace KendoUI.Northwind.Dashboard.Code.Events
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Cqrs.Events;
public class OrderUpdated : IEvent<string>
{
#region Implementation of IEvent
[DataMember]
public Guid Id
{
get
{
return Rsn;
}
set
{
Rsn = value;
}
}
[DataMember]
public int Version { get; set; }
[DataMember]
public DateTimeOffset TimeStamp { get; set; }
#endregion
#region Implementation of IMessageWithAuthenticationToken<string>
public string AuthenticationToken { get; set; }
#endregion
#region Implementation of IMessage
public Guid CorrelationId { get; set; }
/// <summary>
/// The originating framework this message was sent from.
/// </summary>
public string OriginatingFramework { get; set; }
/// <summary>
/// The frameworks this <see cref="T:Cqrs.Messages.IMessage"/> has been delivered to/sent via already.
/// </summary>
public IEnumerable<string> Frameworks { get; set; }
#endregion
[DataMember]
public Guid Rsn { get; set; }
[DataMember]
public int OrderId { get; private set; }
[DataMember]
public string CustomerId { get; private set; }
[DataMember]
public int? EmployeeId { get; private set; }
[DataMember]
public DateTime? OrderDate { get; private set; }
[DataMember]
public DateTime? RequiredDate { get; private set; }
[DataMember]
public DateTime? ShippedDate { get; private set; }
[DataMember]
public int? ShipViaId { get; private set; }
[DataMember]
public decimal? Freight { get; private set; }
[DataMember]
public string ShipName { get; private set; }
[DataMember]
public string ShipAddress { get; private set; }
[DataMember]
public string ShipCity { get; private set; }
[DataMember]
public string ShipRegion { get; private set; }
[DataMember]
public string ShipPostalCode { get; private set; }
[DataMember]
public string ShipCountry { get; private set; }
public OrderUpdated(Guid rsn, int orderId, string customerId, int? employeeId, DateTime? orderDate, DateTime? requiredDate, DateTime? shippedDate, int? shipViaId, decimal? freight, string shipName, string shipAddress, string shipCity, string shipRegion, string shipPostalCode, string shipCountry)
{
Rsn = rsn;
OrderId = orderId;
CustomerId = customerId;
EmployeeId = employeeId;
OrderDate = orderDate;
RequiredDate = requiredDate;
ShippedDate = shippedDate;
ShipViaId = shipViaId;
Freight = freight;
ShipName = shipName;
ShipAddress = shipAddress;
ShipCity = shipCity;
ShipRegion = shipRegion;
ShipPostalCode = shipPostalCode;
ShipCountry = shipCountry;
}
}
}
- Add an
Update
method to theOrder
class you created in Step 3.3 as follows:
// C#
/// <summary>
/// Update an existing Order
/// </summary>
public virtual void UpdateOrder(int orderId, string customerId, int? employeeId, DateTime? orderDate, DateTime? requiredDate, DateTime? shippedDate, int? shipViaId, decimal? freight, string shipName, string shipAddress, string shipCity, string shipRegion, string shipPostalCode, string shipCountry)
{
ApplyChange(new OrderUpdated(Rsn, orderId, customerId, employeeId, orderDate, requiredDate, shippedDate, shipViaId, freight, shipName, shipAddress, shipCity, shipRegion, shipPostalCode, shipCountry));
}
- Add a new class
UpdateOrderCommand
as follows:
// C#
namespace KendoUI.Northwind.Dashboard.Code.Commands
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Cqrs.Commands;
using Cqrs.Entities;
using Models;
/// <summary>
/// A <see cref="ICommand{TAuthenticationToken}"/> that requests an existing order gets updateds.
/// </summary>
public class UpdateOrderCommand : ICommand<string>
{
#region Implementation of ICommand
[DataMember]
public Guid Id
{
get { return Rsn; }
set { Rsn = value; }
}
[DataMember]
public int ExpectedVersion { get; set; }
#endregion
#region Implementation of IMessageWithAuthenticationToken<string>
[DataMember]
public string AuthenticationToken { get; set; }
#endregion
#region Implementation of IMessage
[DataMember]
public Guid CorrelationId { get; set; }
/// <summary>
/// The originating framework this message was sent from.
/// </summary>
public string OriginatingFramework { get; set; }
/// <summary>
/// The frameworks this <see cref="T:Cqrs.Messages.IMessage"/> has been delivered to/sent via already.
/// </summary>
public IEnumerable<string> Frameworks { get; set; }
#endregion
[DataMember]
public Guid Rsn { get; set; }
[DataMember]
public int OrderId { get; private set; }
[DataMember]
public string CustomerId { get; private set; }
[DataMember]
public int? EmployeeId { get; private set; }
[DataMember]
public DateTime? OrderDate { get; private set; }
[DataMember]
public DateTime? RequiredDate { get; private set; }
[DataMember]
public DateTime? ShippedDate { get; private set; }
[DataMember]
public int? ShipViaId { get; private set; }
[DataMember]
public decimal? Freight { get; private set; }
[DataMember]
public string ShipName { get; private set; }
[DataMember]
public string ShipAddress { get; private set; }
[DataMember]
public string ShipCity { get; private set; }
[DataMember]
public string ShipRegion { get; private set; }
[DataMember]
public string ShipPostalCode { get; private set; }
[DataMember]
public string ShipCountry { get; private set; }
public UpdateOrderCommand(Guid rsn, int orderId, string customerId, int? employeeId, DateTime? orderDate, DateTime? requiredDate, DateTime? shippedDate, int? shipViaId, decimal? freight, string shipName, string shipAddress, string shipCity, string shipRegion, string shipPostalCode, string shipCountry)
{
Rsn = rsn;
OrderId = orderId;
CustomerId = customerId;
EmployeeId = employeeId;
OrderDate = orderDate;
RequiredDate = requiredDate;
ShippedDate = shippedDate;
ShipViaId = shipViaId;
Freight = freight;
ShipName = shipName;
ShipAddress = shipAddress;
ShipCity = shipCity;
ShipRegion = shipRegion;
ShipPostalCode = shipPostalCode;
ShipCountry = shipCountry;
}
/// <summary>
/// Explicit cast of <see cref="OrderViewModel"/> to <see cref="UpdateOrderCommand"/>
/// </summary>
/// <param name="order">A <see cref="OrderViewModel"/> <see cref="Entity"/> to convert</param>
/// <returns>A <see cref="CreateOrderCommand"/> object</returns>
public static explicit operator UpdateOrderCommand(OrderViewModel order)
{
var result = new UpdateOrderCommand
(
order.Rsn,
order.OrderID,
order.CustomerID,
order.EmployeeID,
order.OrderDate,
null,
order.ShippedDate,
order.ShipVia,
order.Freight,
order.ShipName,
order.ShipAddress,
order.ShipCity,
null,
order.ShipPostalCode,
order.ShipCountry
);
return result;
}
}
}
- Add a new class
UpdateOrderCommandHandler
as follows:
// C#
namespace KendoUI.Northwind.Dashboard.Code.Commands.Handlers
{
using Cqrs.Domain;
using Cqrs.Commands;
/// <summary>
/// Responds to any <see cref="UpdateOrderCommand"/>, loads the existing <see cref="Order"/> instance and passes the contents of the <see cref="UpdateOrderCommand"/> to it.
/// </summary>
public class UpdateOrderCommandHandler
: ICommandHandler<string, UpdateOrderCommand>
{
protected IUnitOfWork<string> UnitOfWork { get; private set; }
public UpdateOrderCommandHandler(IUnitOfWork<string> unitOfWork)
{
UnitOfWork = unitOfWork;
}
#region Implementation of ICommandHandler<in UpdateOrderCommand>
public void Handle(UpdateOrderCommand command)
{
// As this is a request to update an existing order, load the existing order (which will automatically add it to the UnitOfWork)
Order item = UnitOfWork.Get<Order>(command.Rsn);
// Request the Order be updated
item.UpdateOrder(command.OrderId, command.CustomerId, command.EmployeeId, command.OrderDate, command.RequiredDate, command.ShippedDate, command.ShipViaId, command.Freight, command.ShipName, command.ShipAddress, command.ShipCity, command.ShipRegion, command.ShipPostalCode, command.ShipCountry);
// Commit your changes and publish any events
UnitOfWork.Commit();
}
#endregion
}
}
- Add a new class
OrderUpdatedEventHandler
as follows:
// C#
namespace KendoUI.Northwind.Dashboard.Code.Events.Handlers
{
using cdmdotnet.AutoMapper;
using Cqrs.Events;
using Entities;
using Repositories;
public class OrderUpdatedEventHandler : IEventHandler<string, OrderUpdated>
{
protected IAutomapHelper AutomapHelper { get; private set; }
protected IOrderRepository OrderRepository { get; private set; }
public OrderUpdatedEventHandler(IAutomapHelper automapHelper, IOrderRepository repository)
{
AutomapHelper = automapHelper;
OrderRepository = repository;
}
#region Implementation of IEventHandler<in OrderUpdated>
public void Handle(OrderUpdated @event)
{
// As this is an update of an existing order, load the existing order
OrderEntity entity = OrderRepository.Load(@event.Rsn);
// As the entities match very closely, use the auto-mapper to save writing code.
entity = AutomapHelper.Automap(@event, entity);
// As this is an update of an existing order, pass the updated entity to the Repository to be updated and persisted
OrderRepository.Update(entity);
}
#endregion
}
}
- Modify the
Orders_Update
method in theOrdersController
class as follows:
// C#
public ActionResult Orders_Update([DataSourceRequest]DataSourceRequest request, [ModelBinder(typeof(NullableGuidBinder))]OrderViewModel order)
{
if (ModelState.IsValid)
{
// Cast the view model into an update command, and publish the command, waiting for an OrderUpdated event
// The Telerik Northwind dashboard website is synchronous not asynchronous.
var command = (UpdateOrderCommand)order;
CommandPublisher.PublishAndWait<UpdateOrderCommand, OrderUpdated>(command);
}
return Json(new[] { order }.ToDataSourceResult(request, ModelState));
}
- Compile and run the site.
- Navigate to
PRODUCTS & ORDERS
- Click the
Edit
button that is now visible at the end of a row in the order grid.
You have now replaced the EntityFramework update (database row update) operations with CQRS.NET on an existing website without changing your existing DB in a way that would break any existing code. Your code is now ready for step 5, where we will replace object delete (database row delete) operations that use EntityFramework with CQRS.NET.