Entity Framework CRUD operations with Openlayers Geometry object - entity-framework

I am using Openlayers and trying to save the geometry information in my DB.
When i draw a polygon on openlayers map, the object(feature) generated is in this format
{
"type": "Polygon",
"coordinates": [
[
[
54.86572265625,
74.0013854318592
],
[
53.59130859375,
73.62159408606237
],
[
53.96484375,
73.16953636227885
],
[
55.986328125,
73.59679245247814
]
]
]
}
Above object has 2 properties. {type: string, coordinates: someNestedArray}
I am passing this object to my API to save it in DB. But am facing issue with defining type of coordinates property.
Basically it is of type float[][][] so i created my EF model class as below
public class Geometry
{
public string Type { get; set; }
public float[][][] Coordinates { get; set; }
}
when i try to get/update, EF is throwing below error
{"The property 'Geometry.Coordinates' could not be mapped, because it is of type 'float[][][]'
which is not a supported primitive type or a valid entity type. Either explicitly map this property,
or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'."}
the error is clear. EF cannot map these un-supported types on its own. How can i define a mapping explicitly ? Or is there any way i can make it work ? is the type float[][][] correct ?
Thanks in advance.

You can always save coordinates as string where coordinates are separated by comma.
For instance in FE part you can handle it like this:
const someLine = feature.getGeometry().transform("EPSG:4326",
"EPSG:3857");
const geometryLine = someLine
.clone()
.getGeometry()
.transform("EPSG:3857", "EPSG:4326");
const geometryCoords = geometryLine.getCoordinates().join(";");
Then you will get something like this: "43.520548594674132,26.565803087473146;...." which can be saved to database as a string. (it can be additionally tweaked with fewer decimal points, etc..)
After that, if you want to handle/fetch data through API and map it via automapper(or some custom implementation)to List of Coordinates (for example something like this)
public class Coordinates
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
To map previously saved data to DTO you can use something like this
public class GeneralProfile : Profile
{
public GeneralProfile()
{
CreateMap<Route, GetSavedRouteDTO>()
.ForMember(x => x.TripLength, options => options.MapFrom(x => x.Length))
.ForMember(x => x.RouteCoordinates, options => options.MapFrom(MapFromStringCoordinates));
CreateMap<Route, RouteCreateDTO>().ReverseMap();
}
private List<Coordinates> MapFromStringCoordinates(Route route, GetSavedRouteDTO getSavedRouteDTO)
{
var currentCulture = System.Globalization.CultureInfo.InstalledUICulture;
var numberFormat = (System.Globalization.NumberFormatInfo)currentCulture.NumberFormat.Clone();
numberFormat.NumberDecimalSeparator = ".";
var coordinates = new List<Coordinates>();
var coordinatesSplit = route.Coordinates.Split(";");
foreach (var coord in coordinatesSplit)
{
var currentCoord = coord.Split(",");
if (currentCoord.Length > 1)
{
var latitude = double.Parse(currentCoord[0], numberFormat);
var longitude = double.Parse(currentCoord[1], numberFormat);
var coords= new Coordinates { Latitude = latitude, Longitude = longitude };
coordinates.Add(coords);
}
}
return coordinates;
}
}
With that you ll get the list of coordinates that will contain latitude and longitude and from which will you create geometry entity.

Related

Prioritizing Constraints in linear SolverContext Model using SolverFoundation

Good morning,
I am trying to solve what I believe is a linear problem, using Microsofts SolverFoundation in code (c#). I see most references to this type of solving are related to the Solver inside of Excel, and it indeed does share many similarities. However, I have written up an example of what I am trying to do.
For this example, lets say I have 3 grocery stores (Albertsons, Safeway, Costco), and 3 different types of apples (Red, Green, Fuji).
public enum AppleType
{
Red,
Green,
Fuji,
}
Each of these stores offers these different apple types at different percentages per order.
public class Store
{
public string Name { get; set; }
public List<Apple> ApplesOffered { get; set; }
}
public class Apple
{
public AppleType AppleType { get; set; }
public double OrderPercent { get; set; }
}
Here is my mock-data for this setup.
List<Store> stores = new List<Store>
{
new Store()
{
Name = "Albertsons",
ApplesOffered = new List<Apple>
{
new Apple(){AppleType = AppleType.Red, OrderPercent = 80 },
new Apple(){AppleType = AppleType.Green, OrderPercent = 15 },
new Apple(){AppleType = AppleType.Fuji, OrderPercent = 0 }
}
},
new Store()
{
Name = "Safeway",
ApplesOffered = new List<Apple>
{
new Apple(){AppleType = AppleType.Red, OrderPercent = 12 },
new Apple(){AppleType = AppleType.Green, OrderPercent = 30 },
new Apple(){AppleType = AppleType.Fuji, OrderPercent = 0 }
}
},
new Store()
{
Name = "Costco",
ApplesOffered = new List<Apple>
{
new Apple(){AppleType = AppleType.Red, OrderPercent = 10 },
new Apple(){AppleType = AppleType.Green, OrderPercent = 35 },
new Apple(){AppleType = AppleType.Fuji, OrderPercent = 40 }
}
}
};
Alright, so say I have a list of apple types and I want to choose how many of each I want, and the solver should give me the minimal optimized orders from different stores to get what I want.
my code for building the constraints is as follows:
var context = SolverContext.GetContext();
context.ClearModel();
var model = context.CreateModel();
// Decisions
stores.ForEach(store => model.AddDecisions(new Decision(Domain.RealNonnegative, store.Name)));
// Constraints
var constraints = new List<CustomAppleConstraint>();
stores.ForEach(store =>
{
foreach (AppleType a in (AppleType[])Enum.GetValues(typeof(AppleType)))
{
var ao = store.ApplesOffered.FirstOrDefault(_ => _.AppleType == a);
if (ao != null && ao.OrderPercent > 0)
{
constraints.Add(new CustomAppleConstraint
{
Type = a,
Value = $"0.{ao.OrderPercent} * {store.Name}"
});
}
}
});
// Add Constraints to model
var constraintGroups = constraints.GroupBy(_ => _.Type).ToList();
foreach (AppleType a in (AppleType[])Enum.GetValues(typeof(AppleType)))
{
var group = constraintGroups.FirstOrDefault(_ => _.Key == a);
if (group != null)
{
model.AddConstraint($"_{a}", $"{(string.Join(" + ", group.Select(_ => _.Value).ToArray()))} >= {order[a]}");
}
}
// Solve
var solution = context.Solve(new SimplexDirective());
var solutionResults = new List<KeyValuePair<string, double>>();
foreach (var decision in solution.Decisions)
{
var value = (double)decision.GetValues().First()[0];
solutionResults.Add(new KeyValuePair<string, double>(decision.Name, value));
}
return solutionResults;
I have tested this with a bunch of different orders, and it all appears to be giving me the correct data.
Now say I have the following simple order where I only want green apples:
{AppleType.Red, 0},
{AppleType.Green, 10},
{AppleType.Fuji, 0}
I get back a result suggesting 28.57 orders from Costco, which I would expect because Costco offers the highest percentage of green apples per order.
So here is where I am trying to figure the correct way to implement one more constraint.
Say I have some preferences for which stores I use to get certain apple types. (eg, I only want my green apples from Safeway).
// Apple Type : Preferred Store
var orderPrefs = new Dictionary<AppleType, string>()
{
{AppleType.Red, "Albertsons"},
{AppleType.Green, "Safeway" },
{AppleType.Fuji, "Costco" }
};
So even though Costco provides the highest percentage of green apples, I want to add some constraints from my preferences that prioritize the green apple result from Safeway. In this instance, my prefs say I Only want green apple from Safeway, so 100% of this order should come from Safeway.
Granted this is a very simple example, but its the meat of what I am trying to wrap my head around.
I hope this makes sense... I have been trying to figure this out for a few days now with no luck. Thank you.

Dart: parse api response and dynamically create child T from parent

Looking for a clean way to parse out data from an API.
The API returns data for creating “Boat” and “Car” models wrapped up in metadata.
{
“timestamp” “0000”,
“data”: {
“count” “1”,
“results” [
{
“name”: “boatyMcBoatFace”
}
]
}
}
I want to create 2 classes for the metadata and also the boat/car data using custom fromJson() methods.
Current implementation is something like this
Class Boat {
String name;
Boat.fromJson(json) {
this.name = json[‘name’]
}
static List<Boat> listFromJson(List<dynamic> json) {
return json.map((c) => Boat.fromJson(c)).toList();
}
}
ResponseModel<T> {
String timestamp
DataModel data
ResponseModel.fromJson(json) {
this.timestamp = json[‘timestamp’]
this.data = DataModel<T>.fromJson(json[‘data’])
}
}
DataModel<T> {
String count
List<T> results
DataModel.fromJson(json) {
this.count = json[‘count’]
this.results = json[‘results’] // change this, see below
}
}
Currently I'm creating a ResponseModel, which in turn creates a DataModel.
But then I'm manually creating and setting Boats using:
// yes
final res = methodThatMakesHttpRequest();
final apiResponse = ResponseModel<Boat>.fromJson(res);
// no
final boats = Boat.listFromJson(apiResponse.data.results);
apiResponse.data.results = boats;
Ideally I would remove those last two lines, and instead have Boats get created dynamically within DataModel.fromJson with something like
DataModel.fromJson(json) {
this.count = json[‘count’]
T.listFromJson(json[‘results’])
}
But this of course does not work as T.listFromJson does not exist.

Cleanest way to implement multiple parameters filters in a REST API

I am currently implementing a RESTFUL API that provides endpoints to interface with a database .
I want to implement filtering in my API , but I need to provide an endpoint that can provide a way to apply filtering on a table using all the table's columns.
I've found some patterns such as :
GET /api/ressource?param1=value1,param2=value2...paramN=valueN
param1,param2...param N being my table columns and the values.
I've also found another pattern that consists of send a JSON object that represents the query .
To filter on a field, simply add that field and its value to the query :
GET /app/items
{
"items": [
{
"param1": "value1",
"param2": "value",
"param N": "value N"
}
]
}
I'm looking for the best practice to achieve this .
I'm using EF Core with ASP.NET Core for implementing this.
Firstly be cautious about filtering on everything/anything. Base the available filters on what users will need and expand from that depending on demand. Less code to write, less complexity, fewer indexes needed on the DB side, better performance.
That said, the approach I use for pages that have a significant number of filters is to use an enumeration server side where my criteria fields are passed back their enumeration value (number) to provide on the request. So a filter field would comprise of a name, default or applicable values, and an enumeration value to use when passing an entered or selected value back to the search. The requesting code creates a JSON object with the applied filters and Base64's it to send in the request:
I.e.
{
p1: "Jake",
p2: "8"
}
The query string looks like:
.../api/customer/search?filters=XHgde0023GRw....
On the server side I extract the Base64 then parse it as a Dictionary<string,string> to feed to the filter parsing. For example given that the criteria was for searching for a child using name and age:
// this is the search filter keys, these (int) values are passed to the search client for each filter field.
public enum FilterKeys
{
None = 0,
Name,
Age,
ParentName
}
public JsonResult Search(string filters)
{
string filterJson = Encoding.UTF8.GetString(Convert.FromBase64String(filters));
var filterData = JsonConvert.DeserializeObject<Dictionary<string, string>>(filterJson);
using (var context = new TestDbContext())
{
var query = context.Children.AsQueryable();
foreach (var filter in filterData)
query = filterChildren(query, filter.Key, filter.Value);
var results = query.ToList(); //example fetch.
// TODO: Get the results, package up view models, and return...
}
}
private IQueryable<Child> filterChildren(IQueryable<Child> query, string key, string value)
{
var filterKey = parseFilterKey(key);
if (filterKey == FilterKeys.None)
return query;
switch (filterKey)
{
case FilterKeys.Name:
query = query.Where(x => x.Name == value);
break;
case FilterKeys.Age:
DateTime birthDateStart = DateTime.Today.AddYears((int.Parse(value) + 1) * -1);
DateTime birthDateEnd = birthDateStart.AddYears(1);
query = query.Where(x => x.BirthDate <= birthDateEnd && x.BirthDate >= birthDateStart);
break;
}
return query;
}
private FilterKeys parseFilterKey(string key)
{
FilterKeys filterKey = FilterKeys.None;
Enum.TryParse(key.Substring(1), out filterKey);
return filterKey;
}
You can use strings and constants to avoid the enum parsing, however I find enums are readable and keep the sent payload a little more compact. The above is a simplified example and obviously needs error checking. The implementation code for complex filter conditions such as the age to birth date above would better be suited as a separate method, but it should give you some ideas. You can search for children by name, and/or age, and/or parent's name for example.
I have invented and found it useful to combine a few filters into one type for example CommonFilters and make this type parseable from string:
[TypeConverter(typeof(CommonFiltersTypeConverter))]
public class CommonFilters
{
public PageOptions PageOptions { get; set; }
public Range<decimal> Amount { get; set; }
//... other filters
[JsonIgnore]
public bool HasAny => Amount.HasValue || PageOptions!=null;
public static bool TryParse(string str, out CommonFilters result)
{
result = new CommonFilters();
if (string.IsNullOrEmpty(str))
return false;
var parts = str.Split(new[] { ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
{
if (part.StartsWith("amount:") && Range<decimal>.TryParse(part.Substring(7), out Range<decimal> amount))
{
result.Amount = amount;
continue;
}
if (part.StartsWith("page-options:") && PageOptions.TryParse(part.Substring(13), out PageOptions pageOptions))
{
result.PageOptions = pageOptions;
continue;
}
//etc.
}
return result.HasAny;
}
public static implicit operator CommonFilters(string str)
{
if (TryParse(str, out CommonFilters res))
return res;
return null;
}
}
public class CommonFiltersTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string str)
{
if (CommonFilters.TryParse(str, out CommonFilters obj))
{
return obj;
}
}
return base.ConvertFrom(context, culture, value);
}
}
the request looks like this:
public class GetOrdersRequest
{
[DefaultValue("page-options:50;amount:0.001-1000;min-qty:10")]
public CommonFilters Filters { get; set; }
//...other stuff
}
In this way you reduce the number of input request parameters, especially when some queries don't care about all filters
If you use swagger map this type as string:
c.MapTypeAsString<CommonFilters>();
public static void MapTypeAsString<T>(this SwaggerGenOptions swaggerGenOptions)
{
swaggerGenOptions.MapType(typeof(T), () => new OpenApiSchema(){Type = "string"});
}

How to setup Moq with Callbacks?

Ok, I have started to look at Moq, so this is a noob question.
I have followed the quick guide, and I am trying to setup a callback to return a specific model:
void Main()
{
var resultData = new MyModel();
var mock = new Mock<IMyClass>();
mock.Setup(x => x.Register(It.IsAny<string>()))
.Returns(new MyModel { Name = "Test" })
.Callback<MyModel>((data) =>
{
resultData = data;
});
var parameter = "123";
var result = mock.Object.Register(parameter);
}
public interface IMyClass
{
MyModel Register(string code);
}
public class MyModel
{
public string Name { get; set; }
}
I get this exception on the call:
ArgumentException: Object of type 'System.String' cannot be converted
to type 'UserQuery+MyModel'.
What am I doing wrong?
The T in the Callback<T> method should match the parameter type of the method being Setup. In other words, Moq is letting you set a callback method with the same parameters as the method being mocked.
I'm not exactly sure what you're trying to do here. If you're just trying to save the return MyModel object from your mocked method, do this:
var returnedModel = new MyModel { Name = "Test" };
mock.Setup(x => x.Register(It.IsAny<string>()))
.Returns(returnedModel);
If you're trying to create a MyModel with the given string parameter, do this:
mock.Setup(x => x.Register(It.IsAny<string>()))
.Returns((string data) => new MyModel { Name = data });

Unable to cast object of type Entity to Type ActivityParty

Im working with a custom plugin for CRM online 2015 and every time I try to access the activityparty from the field "Email.To" I get
"base {System.SystemException} = {"Unable to cast object of type 'Microsoft.Xrm.Sdk.Entity' to type ...ActivityParty'."}"
Here is how my code looks like:
public class PreCreate : Plugin
{
public PreCreate()
: base(typeof(PreCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Create", "email", new Action<LocalPluginContext>(ExecutePreEntityCreate)));
}
public void ExecutePreEntityCreate(LocalPluginContext localContext)
{
var target = (Entity)localContext.PluginExecutionContext.InputParameters["Target"];
using (var context = new XrmServiceContext(localContext.OrganizationService))
{
var email = target.ToEntity<Email>(); //The entity has the right values
var activityPartyList=email.To // here I see the exception
//If I use the following code:
var activityParty = email.GetAttributeValue<EntityCollection>("to");
//I get an empty ActivityParty(empty Id)
}
}
}
Do I have to do some initialization for activityparty types?
There is no issue with the code, the field Email.To will return a EntityCollection and to obtain that you need to use:
var entityCollection = email.GetAttributeValue<EntityCollection>("to");
This will give you a collection of entities that need to be converted to ActivityParty(entityCollection.Entities).
To convert the Entities you need to:
foreach (var entityItem in entityCollection.Entities)
{
var ap = entityItem.ToEntity<ActivityParty>();
//Here you will get the LogicalName in this case Lead
// the Id and the name
var leadId = ap.PartyId.Id;
//To get the Lead
var lead=context.LeadSet.FirstOrDefault(l => l.Id == leadId);
}