What should be the best practice in Domain and DTO mapping - mapper

I have task to make AbsenceDTO with two properties DateFrom and DateTO where the Domain Absence can be a single day with three properties Day, Month and Year. Bellow is the code sample:
public class Absence
{
#region Properties
/// <summary>
/// A unique id
/// </summary>
public int Id { get; set; }
/// <summary>
/// Day of the absence
/// </summary>
public int Day { get; set; }
/// <summary>
/// Month of the absence
/// </summary>
public int Month { get; set; }
/// <summary>
/// Year of the absence
/// </summary>
public int Year { get; set; }
}
public class AbsenceDTO
{
private List<Absence> absences = null;
public AbsenceDTO()
{
}
public AbsenceDTO(List<Absence> absences)
{
this.absences = absences;
}
public DateTime DateFrom
{
get
{
return //TO DO
}
}
public DateTime DateTO
{
get
{
return //TO DO
}
}
}
So here how should I calculate DTO Date properties and what should be the best pattern/practice in making mapper/converter?

Related

Shopify with Newtonsoft (JSON.NET) issue

I'm having an issue I can't figure out with a WCF service I'm building, where I am getting the error:
"Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data
contract which is not supported. Consider modifying the definition of
collection 'Newtonsoft.Json.Linq.JToken' to remove references to
itself"
I know the main solution is to uncheck the option to reuse that Newtonsoft reference in my service references, but I don't have that option listed to uncheck. I confirmed json.net is being referenced properly in my service.
The weird thing is I confirmed I am getting results when I leave this call
public List<T> CallService<T>(string query)
{
var data = new List<T>();
var fullyEscapedUri = _ShopUri.AbsoluteUri.EndsWith("/") ? _ShopUri : new Uri(_ShopUri + "/");
var uri = new Uri(fullyEscapedUri, typeof(T).Name);
if (!string.IsNullOrWhiteSpace(query))
{
var uriBuilder = new UriBuilder(uri) { Query = query };
uri = uriBuilder.Uri;
}
string url = String.Format("{0}{1}", _ShopUri, query);
var request = WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
string base64EncodedUsernameAndPassword = string.Format("{0}:{1}", _Username, _Password);
string authHeader = string.Format("Basic {0}", Convert.ToBase64String(Encoding.UTF8.GetBytes(base64EncodedUsernameAndPassword)));
request.Headers["Authorization"] = authHeader;
using (var response = request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
string json = reader.ReadToEnd();
var jsonObj = JsonConvert.DeserializeObject(json, new JsonSerializerSettings()
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
}) as JObject;
var jsonArray = jsonObj[_ObjectType] as JArray;
foreach (var jsonEmp in jsonArray)
{
var obj = JsonConvert.DeserializeObject<T>(jsonEmp.ToString());
data.Add(obj);
}
}
}
}
return data;
}
This method is in a custom class I wrote, so a couple of the variables appear as though they aren't definied - I'd be posted a sh*tton of code. But as you can see, I need this method to dynamically call any Shopify endpoint. In this example, the _ObjectType variable going in the first time is "orders."
Here is my order class definition:
public class Orders : ShopifyObject
{
[JsonProperty(PropertyName = "orders")]
public List<Order> orders;
}
public class Order : ShopifyObject
{
/// <summary>
/// The mailing address associated with the payment method. This address is an optional field that will not be available on orders that do not require one.
/// </summary>
[JsonProperty("billing_address")]
public Address BillingAddress { get; set; }
/// <summary>
/// The IP address of the browser used by the customer when placing the order.
/// </summary>
[JsonProperty("browser_ip")]
public string BrowserIp { get; set; }
/// <summary>
/// Indicates whether or not the person who placed the order would like to receive email updates from the shop.
/// This is set when checking the "I want to receive occasional emails about new products, promotions and other news" checkbox during checkout.
/// </summary>
[JsonProperty("buyer_accepts_marketing")]
public bool? BuyerAcceptsMarketing { get; set; }
/// <summary>
/// The reason why the order was cancelled. If the order was not cancelled, this value is null. Known values are "customer", "fraud", "inventory" and "other".
/// </summary>
[JsonProperty("cancel_reason")]
public string CancelReason { get; set; }
/// <summary>
/// The date and time when the order was cancelled. If the order was not cancelled, this value is null.
/// </summary>
[JsonProperty("cancelled_at")]
public DateTimeOffset? CancelledAt { get; set; }
/// <summary>
/// Unique identifier for a particular cart that is attached to a particular order.
/// </summary>
[JsonProperty("cart_token")]
public string CartToken { get; set; }
/// <summary>
/// A <see cref="ShopifySharp.ClientDetails"/> object containing information about the client.
/// </summary>
[JsonProperty("client_details")]
public ClientDetails ClientDetails { get; set; }
/// <summary>
/// The date and time when the order was closed. If the order was not clsoed, this value is null.
/// </summary>
[JsonProperty("closed_at")]
public DateTimeOffset? ClosedAt { get; set; }
/// <summary>
/// The customer's contact email address.
/// </summary>
[JsonProperty("contact_email"), Obsolete("ContactEmail is not documented by Shopify and will be removed in a future release.")]
public string ContactEmail { get; set; }
/// <summary>
/// The date and time when the order was created in Shopify.
/// </summary>
[JsonProperty("created_at")]
public DateTimeOffset? CreatedAt { get; set; }
/// <summary>
/// The three letter code (ISO 4217) for the currency used for the payment.
/// </summary>
[JsonProperty("currency")]
public string Currency { get; set; }
/// <summary>
/// A <see cref="ShopifySharp.Customer"/> object containing information about the customer. This value may be null if the order was created through Shopify POS.
/// </summary>
[JsonProperty("customer")]
public Customer Customer { get; set; }
/// <summary>
/// Applicable discount codes that can be applied to the order.
/// </summary>
[JsonProperty("discount_codes")]
public IEnumerable<DiscountCode> DiscountCodes { get; set; }
/// <summary>
/// The order's email address. Note: On and after 2015-11-03, you should be using <see cref="ContactEmail"/> to refer to the customer's email address.
/// Between 2015-11-03 and 2015-12-03, updates to an order's email will also update the customer's email. This is temporary so apps can be migrated over to
/// doing customer updates rather than order updates to change the contact email. After 2015-12-03, updating updating an order's email will no longer update
/// the customer's email and apps will have to use the customer update endpoint to do so.
/// </summary>
[JsonProperty("email")]
public string Email { get; set; }
/// <summary>
/// The financial status of an order. Known values are "authorized", "paid", "pending", "partially_paid", "partially_refunded", "refunded" and "voided".
/// </summary>
[JsonProperty("financial_status")]
public string FinancialStatus { get; set; }
/// <summary>
/// An array of <see cref="Fulfillment"/> objects for this order.
/// </summary>
[JsonProperty("fulfillments")]
public IEnumerable<Fulfillment> Fulfillments { get; set; }
/// <summary>
/// The fulfillment status for this order. Known values are 'fulfilled', 'null' and 'partial'.
/// </summary>
[JsonProperty("fulfillment_status")]
public string FulfillmentStatus { get; set; }
/// <summary>
/// Tags are additional short descriptors, commonly used for filtering and searching, formatted as a string of comma-separated values.
/// </summary>
[JsonProperty("tags")]
public string Tags { get; set; }
/// <summary>
/// The URL for the page where the buyer landed when entering the shop.
/// </summary>
[JsonProperty("landing_site")]
public string LandingSite { get; set; }
/// <summary>
/// An array of <see cref="LineItem"/> objects, each one containing information about an item in the order.
/// </summary>
[JsonProperty("line_items")]
public IEnumerable<LineItem> LineItems { get; set; }
/// <summary>
/// The unique numeric identifier for the physical location at which the order was processed. Only present on orders processed at point of sale.
/// </summary>
[JsonProperty("location_id")]
public long? LocationId { get; set; }
/// <summary>
/// The customer's order name as represented by a number, e.g. '#1001'.
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// The text of an optional note that a shop owner can attach to the order.
/// </summary>
[JsonProperty("note")]
public string Note { get; set; }
/// <summary>
/// Extra information that is added to the order.
/// </summary>
[JsonProperty("note_attributes")]
public IEnumerable<NoteAttribute> NoteAttributes { get; set; }
/// <summary>
/// Numerical identifier unique to the shop. A number is sequential and starts at 1000.
/// </summary>
[JsonProperty("number")]
public int? Number { get; set; }
/// <summary>
/// A unique numeric identifier for the order. This one is used by the shop owner and customer.
/// This is different from the id property, which is also a unique numeric identifier for the order, but used for API purposes.
/// </summary>
[JsonProperty("order_number")]
public int? OrderNumber { get; set; }
/// <summary>
/// The URL pointing to the order status web page. The URL will be null unless the order was created from a checkout.
/// </summary>
[JsonProperty("order_status_url")]
public string OrderStatusUrl { get; set; }
/// <summary>
/// Payment details for this order. May be null if the order was created via API without payment details.
/// </summary>
[JsonProperty("payment_details"), Obsolete("PaymentDetails has been deprecated and will be removed in a future release. This data is now available via the Transaction API.")]
public PaymentDetails PaymentDetails { get; set; }
/// <summary>
/// The list of all payment gateways used for the order.
/// </summary>
[JsonProperty("payment_gateway_names")]
public IEnumerable<string> PaymentGatewayNames { get; set; }
/// <summary>
/// The date that the order was processed at.
/// </summary>
[JsonProperty("processed_at")]
public DateTimeOffset? ProcessedAt { get; set; }
/// <summary>
/// The type of payment processing method. Known values are 'checkout', 'direct', 'manual', 'offsite', 'express', 'free' and 'none'.
/// </summary>
[JsonProperty("processing_method")]
public string ProcessingMethod { get; set; }
/// <summary>
/// The website that the customer clicked on to come to the shop.
/// </summary>
[JsonProperty("referring_site")]
public string ReferringSite { get; set; }
/// <summary>
/// The list of <see cref="Refund"/> objects applied to the order
/// </summary>
[JsonProperty("refunds")]
public IEnumerable<Refund> Refunds { get; set; }
/// <summary>
/// The mailing address to where the order will be shipped. This address is optional and will not be available on orders that do not require one.
/// </summary>
[JsonProperty("shipping_address")]
public Address ShippingAddress { get; set; }
/// <summary>
/// An array of <see cref="ShippingLine"/> objects, each of which details the shipping methods used.
/// </summary>
[JsonProperty("shipping_lines")]
public IEnumerable<ShippingLine> ShippingLines { get; set; }
/// <summary>
/// Where the order originated. May only be set during creation, and is not writeable thereafter.
/// Orders created via the API may be assigned any string of your choice except for "web", "pos", "iphone", and "android".
/// Default is "api".
/// </summary>
[JsonProperty("source_name")]
public string SourceName { get; set; }
/// <summary>
/// Price of the order before shipping and taxes
/// </summary>
[JsonProperty("subtotal_price")]
public decimal? SubtotalPrice { get; set; }
/// <summary>
/// An array of <see cref="TaxLine"/> objects, each of which details the total taxes applicable to the order.
/// </summary>
[JsonProperty("tax_lines")]
public IEnumerable<TaxLine> TaxLines { get; set; }
/// <summary>
/// States whether or not taxes are included in the order subtotal.
/// </summary>
[JsonProperty("taxes_included")]
public bool? TaxesIncluded { get; set; }
/// <summary>
/// Unique identifier for a particular order.
/// </summary>
[JsonProperty("token")]
public string Token { get; set; }
/// <summary>
/// The total amount of the discounts applied to the price of the order.
/// </summary>
[JsonProperty("total_discounts")]
public decimal? TotalDiscounts { get; set; }
/// <summary>
/// The sum of all the prices of all the items in the order.
/// </summary>
[JsonProperty("total_line_items_price")]
public decimal? TotalLineItemsPrice { get; set; }
/// <summary>
/// The sum of all the prices of all the items in the order, with taxes and discounts included (must be positive).
/// </summary>
[JsonProperty("total_price")]
public decimal? TotalPrice { get; set; }
/// <summary>
/// The sum of all the prices of all the items in the order, in USD, with taxes and discounts included (must be positive).
/// </summary>
[JsonProperty("total_price_usd"), Obsolete("TotalPriceUsd is not documented by Shopify and will be removed in a future release.")]
public decimal? TotalPriceUsd { get; set; }
/// <summary>
/// The sum of all the taxes applied to the order (must be positive).
/// </summary>
[JsonProperty("total_tax")]
public decimal? TotalTax { get; set; }
/// <summary>
/// The sum of all the weights of the line items in the order, in grams.
/// </summary>
[JsonProperty("total_weight")]
public long? TotalWeight { get; set; }
/// <summary>
/// The date and time when the order was last modified.
/// </summary>
[JsonProperty("updated_at")]
public DateTimeOffset? UpdatedAt { get; set; }
/// <summary>
/// The unique numerical identifier for the user logged into the terminal at the time the order was processed at. Only present on orders processed at point of sale.
/// </summary>
[JsonProperty("user_id")]
public long? UserId { get; set; }
/// <summary>
/// An array of <see cref="Transaction"/> objects that detail all of the transactions in
/// this order.
/// </summary>
[JsonProperty("transactions")]
public IEnumerable<Transaction> Transactions { get; set; }
}
I seem to be getting the error msg referenced above when it makes this GetOrders() call from the client:
ProductService.ProductServiceClient productService = new ProductService.ProductServiceClient();
OrderService.OrderServiceClient service = new OrderService.OrderServiceClient();
var orders = service.GetOrders(String.Format("orders.json?created_at_min={0}&created_at_max={1}", min, max));
strong text
I've searched my client app for any and all references to Newtonsoft, but I am not finding anything or any clue that would suggest it's being called "recursively." I've deleted and re-added the service references, same issue.
Both the service and client are v4.6.1.
Any ideas?
Ben
EDIT: I can't trigger the error now for some reason, but when it did happen, I got this as the outer exception, followed by just the main error message with the inner exception:
Unhandled Exception: System.ServiceModel.CommunicationException: An error occurred while receiving the HTTP response to http://localhost:3000/OrderService.svc/GetOrders. This could be due to the service endpoint
binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down).
See server logs for more details.
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive.
---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ShopifyServiceClient.OrderService.IOrderService.GetOrders(String query)
at ShopifyServiceClient.OrderService.OrderServiceClient.GetOrders(String query)
at ShopifyServiceClient.Program.Main(String[] args)
Deeper down....
System.Runtime.Serialization.InvalidDataContractException,
System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data
contract which is not supported. Consider modifying the definition of
collection 'Newtonsoft.Json.Linq.JToken' to remove references to
itself.
Here is the entry point of my service:
public class OrderService : IOrderService
{
public ReturnContract GetOffset()
{
return new ReturnContract { Offset = new DateTimeOffset(DateTime.Now) };
}
//non-async calls
public List<Order> GetOrders(string query)
{
OrderData orders = new OrderData(query);
return orders.CallOrders();
}
[DataContract]
[KnownType(typeof(DateTimeOffset))]
public class ReturnContract
{
[DataMember]
public DateTimeOffset? Offset { get; set; }
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
CallOrders() implementation and CallService<T> method that shows type Order going into the method:
internal class OrderData
{
private string _shopifyStore = Global.EcomShop;
private string _apiKey = Global.EcomShopAPIKey;
private string _apiPassword = Global.EcomShopAPIPassword;
private string _query;
internal OrderData(string query)
{
_query = query;
}
internal List<Order> CallOrders()
{
var orderService = new ShopifyService(_shopifyStore, _apiKey, _apiPassword, "orders");
var orders = orderService.CallService<Order>(_query);
return orders;
}
}
Well, in this case it turned out to be a JSON deserialization issue. When this has happened in the past, I've received the "object reference not set to an instance of an object" error. I thought this was weird since I did see Shopify objects coming back from the service.

Datatables pagination does not work

Hello i have following code
jQuery datatables plugin (VIEW)
<script type="text/javascript">
$(document).ready(function () {
$('#table1').DataTable({
/* PROCESS NOTIFICATION */
"processing": true,
/* SERVER SIDE PROCESSING */
"serverSide": true,
"ajax":
{
"url": "GetNonstandardProgram",
"type": "POST"
},
"columnDefs":
[
/* HIDE ID COLUMN */
{
"targets": [ 0 ],
"visible": false,
"searchable": false
},
/* ACTION COLUMN */
{
"aTargets": [-1],
"mData": null,
"mRender": function (data, type, full) {
return 'test';
}
}
],
"bSort":false,
"bPaginate":true,
"iDisplayStart": 5,
"iDisplayLength": 2
});
});
class for parameters which i downloaded (MODEL)
/// <summary>
/// Class that encapsulates most common parameters sent by DataTables plugin
/// </summary>
public class jQueryDataTableParamModel
{
/// <summary>
/// Request sequence number sent by DataTable,
/// same value must be returned in response
/// </summary>
public string sEcho { get; set; }
/// <summary>
/// Text used for filtering
/// </summary>
public string sSearch { get; set; }
/// <summary>
/// Number of records that should be shown in table
/// </summary>
public int iDisplayLength { get; set; }
/// <summary>
/// First record that should be shown(used for paging)
/// </summary>
public int iDisplayStart { get; set; }
/// <summary>
/// Number of columns in table
/// </summary>
public int iColumns { get; set; }
/// <summary>
/// Number of columns that are used in sorting
/// </summary>
public int iSortingCols { get; set; }
/// <summary>
/// Comma separated list of column names
/// </summary>
public string sColumns { get; set; }
}
method which is fired by jQuery (CONTROLLER)
public JsonResult GetNonstandardProgram(SWIN.Models.jQueryDataTableParamModel param)
{
but in this step is a problem.
all values are zeroes or null.
So the question is, why i dont see any parameter values ?!
The datatables is sending this parameters via POST
...
&start=5
&length=2
&search[value]=
...
&search[regex]=false
Thank you
i figured it out.
I changed name of the parameters in the class
public class jQueryDataTableParamModel
{
to this
/// <summary>
/// Number of records that should be shown in table
/// </summary>
public int length { get; set; }
//public int iDisplayLength { get; set; }
/// <summary>
/// First record that should be shown(used for paging)
/// </summary>
public int start { get; set; }
//public int iDisplayStart { get; set; }
and just used param.start and param.length

RavenDB - Computed Properties

I have a document with a few computed properties. Properties that have no setter and can call other methods on my class to return a result, example:
public class Order
{
public string CustomerId { get; set; }
public string VehicleId { get; set; }
public DateTime OrderDate { get; set; }
public decimal CommissionPercent { get; set; }
public List<OrdersLines> OrderLines { get; set; }
public decimal Total
{
get { return GetOrderLinesTotal() + SomeDecimal + AnotherDecimal; }
}
public decimal GetOrderLinesTotal()
{
return OrderLines.Sum(x => x.Amount);
}
}
I use a simple index to search for Orders by customer, date and some properties on the Vehicle document using lucene query and a Transformer to create my view models. I've looked at Scripted Index Results and I'm not sure if it would apply in this case.
public class ViewModel
{
public string OrderId { get; set; }
public string CustomerName { get; set; }
public string VehicleName { get; set; }
public string Total { get; set; }
}
How do i get the computed value from the Total property when I query these documents?
I've simplified the GetOrderLinesTotal some what, in fact it is a complex method that takes a lot of other properties into account when calculating the total.
I only get the computed value that serialized when the document was created or updated.
I realized that this is more a of a document design problem rather than trying to do something RavenDB was not meant to do. I simplified my document and used a map/reduce to solve the problem.
I think your situation is similar to a problem I once encountered. I use a JsonIgnore attribute on my public get property and use a private backing field, which I include in serialisation using the JsonProperty attribute. You should be able to apply a similar idea hopefully:
/// <summary>
/// The <see cref="Team" /> class.
/// </summary>
public class Team
{
/// <summary>
/// The ids of the users in the team.
/// </summary>
[JsonProperty(PropertyName = "UserIds")]
private ICollection<string> userIds;
// ...[snip]...
/// <summary>
/// Gets the ids of the users in the team.
/// </summary>
/// <value>
/// The ids of the users in the team.
/// </value>
[JsonIgnore]
public IEnumerable<string> UserIds
{
get { return this.userIds; }
}
// ...[snip]...
}

RavenDB Spatial Queries Not Returning Results

I'm getting 0 results with the following, which I don't think should be the case.
Query code:
var sourceResults = session.Advanced.LuceneQuery<Route>("Routes/BySource")
.WithinRadiusOf(5, toMatch.Source.Location.Latitude, toMatch.Source.Location.Longitude)
.WhereBetween(r => r.DateTime, minDateTime, maxDateTime).ToArray();
Index Code:
/// <summary>
/// Index for spatial search by route source.
/// </summary>
public class Routes_BySource : AbstractIndexCreationTask<Route>
{
public Routes_BySource()
{
Map = routes => from r in routes
select new { _ = SpatialIndex.Generate(r.Source.Location.Latitude, r.Source.Location.Longitude) };
}
}
Model:
public class Route
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>
/// The id.
/// </value>
public string Id { get; set; }
/// <summary>
/// Gets or sets the source.
/// </summary>
/// <value>
/// From.
/// </value>
public Address Source { get; set; }
/// <summary>
/// Gets or sets destination.
/// </summary>
/// <value>
/// To.
/// </value>
public Address Destination { get; set; }
/// <summary>
/// Gets or sets the id of the user who requested the route.
/// </summary>
/// <value>
/// The user id.
/// </value>
public string UserId { get; set; }
/// <summary>
/// Gets or sets the date time that the request is for.
/// </summary>
/// <value>
/// The date time.
/// </value>
public DateTime DateTime { get; set; }
}
public class Address
{
/// <summary>
/// Gets or sets the name. This is the formatted full name of the address.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the location.
/// </summary>
/// <value>
/// The location.
/// </value>
public Location Location { get; set; }
}
public class Location
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
Unit test (calls the query code)
using (var session = Common.DocumentStore.OpenSession())
{
var routeService = new RouteService(session);
var newRoute = new Route
{
Id = Guid.NewGuid().ToString(),
DateTime = DateTime.Now,
UserId = "user",
Source = new Address { Name = "101 W. 79th St. NY, NY", Location = new Location { Latitude = 32, Longitude = 72 } },
Destination = new Address { Name = "101 W. 79th St. NY, NY", Location = new Location { Latitude = 32, Longitude = 72 } }
};
routeService.Save(newRoute);
var routes = routeService.Search(newRoute);
Assert.IsTrue(routes.Any());
}
Any idea what I'm doing wrong here? Seems like it should be pretty straightforward...
Thanks
In your code you have routeService.Save(newRoute);, I'm used to seeing session.Store(newRoute); then session.SaveChanges();
Things don't get written to the database until you call session.SaveChanges();
But you need to give ravenDB time to index the changes. I suggest to use the "wait for non stale results", I don't remember the code for that right now but if you google ravendb non-stale results.

NHibernate projection, AutoMapping, IPagedList, how to?

I have these entities and models:
ENTITIES:
public class BlogPost {
public virtual int Id { get; set; }
public virtual IList<Keyword> Keywords { get; set; }
public virtual IList<BlogComment> Comments { get; set; }
}
public class BlogComment {
public virtual int Id { get; set; }
public virtual BlogPost Post { get; set; }
}
public class Keyword {
public virtual int Id { get; set; }
public virtual IList<BlogPost> BlogPosts { get; set; }
}
VIEW-MODELS:
public class BlogPostModel {
public int Id { get; set; }
// instead of IList<BlogComment> I have this:
public int CommentsCount { get; set; }
public IList<KeywordModel> Keywords { get; set; }
}
public class KeywordModel {
public int Id { get; set; }
public IList<BlogPostModel> Posts { get; set; }
}
public class BlogCommentModel {
public int Id { get; set; }
public BlogPostModel Post { get; set; }
}
Now I want to load a paged-list of blog-posts with their keywords and comments count and map them by AutoMapper library to a IPagedList<BlogPostModel>. Can you help me please? I'm using the Mvc IPagedList available at nuget:
public interface IPagedList<out T> : IPagedList, IEnumerable<T> {
T this[int index] { get; }
int Count { get; }
IPagedList GetMetaData();
}
public interface IPagedList {
int PageCount { get; }
int TotalItemCount { get; }
int PageNumber { get; }
int PageSize { get; }
bool HasPreviousPage { get; }
bool HasNextPage { get; }
bool IsFirstPage { get; }
bool IsLastPage { get; }
int FirstItemOnPage { get; }
int LastItemOnPage { get; }
}
I test many ways and googled the issue, but I can't find any solution. Thanks for any suggestion.
I had the same problem, and found the way how to fix it, probably this approach will help you too.
public class GenericModelViewConverter<TModel, TView> : IModelViewConverter<TModel, TView>
where TModel : class
where TView : class
{
/// <summary>
/// Initializes a new instance of the <see cref="GenericModelViewConverter{TModel, TView}"/> class.
/// </summary>
public GenericModelViewConverter()
{
// It is not he best place to create the mapping here
Mapper.CreateMap<TView, TModel>();
Mapper.CreateMap<TView, TModel>().ReverseMap();
}
/// <summary>
/// Converts the view to model.
/// </summary>
/// <param name="view">The view as a source.</param>
/// <param name="model">The model as a destination value.</param>
/// <returns>The destination model.</returns>
public virtual TModel ConvertViewToModel(TView view, TModel model = null)
{
return model == null ? Mapper.Map<TView, TModel>(view) : Mapper.Map(view, model);
}
/// <summary>
/// Converts the model to view.
/// </summary>
/// <param name="model">The model as a source.</param>
/// <param name="view">The view as a destination.</param>
/// <returns>The destination view.</returns>
public virtual TView ConvertModelToView(TModel model, TView view = null)
{
return view == null ? Mapper.Map<TModel, TView>(model) : Mapper.Map(model, view);
}
/// <summary>
/// Converts the view to model.
/// </summary>
/// <param name="viewCollection">The collection of views.</param>
/// <returns>The collection of models.</returns>
public virtual IEnumerable<TModel> ConvertViewToModel(IEnumerable<TView> viewCollection)
{
return Mapper.Map<IEnumerable<TView>, HashSet<TModel>>(viewCollection);
}
/// <summary>
/// Converts the model to view.
/// </summary>
/// <param name="modelCollection">The collection of models.</param>
/// <returns>The collection of views.</returns>
public virtual IEnumerable<TView> ConvertModelToView(IEnumerable<TModel> modelCollection)
{
return Mapper.Map<IEnumerable<TModel>, HashSet<TView>>(modelCollection);
}
/// <summary>
/// Converts the model to view.
/// </summary>
/// <param name="modelCollection">The model collection.</param>
/// <returns>The collection of models.</returns>
public virtual IPagedCollection<TView> ConvertModelToView(IPagedCollection<TModel> modelCollection)
{
var list = modelCollection.ToList();
var resultList = ConvertModelToView(list);
return new PagedCollection<TView>(resultList, modelCollection.PageIndex, modelCollection.PageSize, modelCollection.TotalItemCount);
}
/// <summary>
/// Converts the view to model.
/// </summary>
/// <param name="viewCollection">The view collection.</param>
/// <returns>The collection of views.</returns>
public virtual IPagedCollection<TModel> ConvertViewToModel(IPagedCollection<TView> viewCollection)
{
var list = viewCollection.ToList();
var resultList = ConvertViewToModel(list);
return new PagedCollection<TModel>(resultList, viewCollection.PageIndex, viewCollection.PageSize, viewCollection.TotalItemCount);
}
}