NPoco / PetaPoco and Noda Time types - petapoco

I'm just starting to play around with NPoco, but as of yet I haven't located what I need in the docs.
For instance, let's say I have a field Created, which is an Instant in my domain, but a DateTimeOffset set to UTC in my database. Is there a way to have NPoco convert these types?

I expanded on the interface that Schotime demonstrated and built it out for several NodaTime types. Too big to paste here, so here is a GIST.
Note that it doesn't include ZonedDateTime, which would have to be serialized to two different fields, so I'm not sure how NPoco would deal with that. I also didn't include Period, since there's no great corresponding type other than a varchar.
Warning: This code is completely untested. I'm just applying what I know about Noda Time conversions to the overrides that the other answer illustrated. Please test it thoroughly before using in your code.

This is pretty easy. The example below is what is used to deal with the PostgreSQL datetime types, however you can probably adapt this code fairly easy.
public class Mapper : DefaultMapper
{
public override Func<object, object> GetFromDbConverter(Type DestType, Type SourceType)
{
if (DestType == typeof(DateTimeOffset) || DestType == typeof(DateTimeOffset?)
|| DestType == typeof(DateTime) || DestType == typeof(DateTime?))
{
return x =>
{
if (x is NpgsqlTimeStampTZ)
{
if (DestType == typeof(DateTime))
return (DateTime)((NpgsqlTimeStampTZ)x);
if (DestType == typeof(DateTime?))
return (DateTime?)((NpgsqlTimeStampTZ)x);
if (DestType == typeof(DateTimeOffset))
return (DateTimeOffset)((NpgsqlTimeStampTZ)x);
if (DestType == typeof(DateTimeOffset?))
return (DateTimeOffset?)((NpgsqlTimeStampTZ)x);
}
if (x is NpgsqlTimeStamp)
{
if (DestType == typeof(DateTime))
return (DateTime)((NpgsqlTimeStamp)x);
if (DestType == typeof(DateTime?))
return (DateTime?)((NpgsqlTimeStamp)x);
}
if (x is NpgsqlDate)
{
if (DestType == typeof(DateTime))
return (DateTime)((NpgsqlDate)x);
if (DestType == typeof(DateTime?))
return (DateTime?)((NpgsqlDate)x);
}
return x;
};
}
return base.GetFromDbConverter(DestType, SourceType);
}
public override Func<object, object> GetToDbConverter(Type DestType, Type SourceType)
{
if (SourceType == typeof(Instance)) {
return x => { return ((Instance)x).ToDateTimeOffset(); } // etc or something like this
}
return base.GetToDbConverter(DestType, SourceType);
}
}
If you have any further questions post a question to the issues page on github.
Cheers,
Adam

Related

How to find if items in 2 list match (but can't use direct equality)

I have this code here, to see if the items in both lists are identical:
for (final car in this.cars) {
bool found = false;
for (final car2 in garage2.cars) {
if (car2.id == car.id) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
(I previously check if the 2 list lengths are equal). Is there a way to rewrite that so that I don't have O(n2) complexity?
As an option you can override quals and hashcode methods for class Car
something like this
class Car {
int id;
// other fields
#override
bool operator ==(Object o) => o is Car && id == o.id;
#override
int get hashCode => id.hashCode;
}
and then you can use the native method listEquals, which compares for deep equality.
import 'package:flutter/foundation.dart';
bool isEqual = listEquals<Car>(cars, garage2.cars);

break or return from when expressions

What I would like to do:
when(transaction.state) {
Transaction.Type.EXPIRED,
//about 10 more types
Transaction.Type.BLOCKED -> {
if (transaction.type == Transaction.Type.BLOCKED && transaction.closeAnyway) {
close(transaction)
break //close if type is blocked and has 'closeAnyway' flag
}
//common logic
}
//other types
}
I cannot write break:
'break' and 'continue' are not allowed in 'when' statements. Consider using labels to continue/break from the outer loop.
Is it a way to return/break from when statements? Or what is the best way to solve it?
You can use run with a return at label:
when(transaction.state) {
Transaction.Type.EXPIRED,
//about 10 more types
Transaction.Type.BLOCKED -> run {
if (transaction.type == Transaction.Type.BLOCKED && transaction.closeAnyway) {
close(transaction)
return#run //close if type is blocked and has 'closeAnyway' flag
}
//common logic
}
//other types
}
You can use labels to break/continue/return. e.g.:
transactions# for (transaction in transactions) {
when (transaction.state) {
Transaction.Type.EXPIRED,
Transaction.Type.BLOCKED -> {
break#transactions
}
}
}
See Returns and Jumps - Kotlin Programming Language for more details.
Work around using apply():
transaction.apply {
when(state) {
Transaction.Type.EXPIRED,
//about 10 more types
Transaction.Type.BLOCKED -> {
if (type == Transaction.Type.BLOCKED && closeAnyway) {
close(this)
return#apply
}
//common logic
}
//other types
}
}

How can i return different types from my method?

I have a method which returns an object (this._response) which is of type IResponse. I want to return this._response.details which is of type IDetails.
get response(): IResponse {
if (this._response.response.header.statusCode === "0000" || this._response.response.header.statusCode === "YHOO") {
return this._response.details; //IDetails
} else if (this._response.response.header.statusCode === "6621" || this._response.response.header.statusCode === "6622") {
this._response.response.isViewError = true;
} else {
this._response.response.showError = this._response.response.header;
}
return this._response //IResponse
}
[ts] Property 'details' does not exist on type 'IResponse'.
How can I return different types from method based on if condition?
You can use union types:
get response(): IDetails | IResponse {
...
}
Edit
The problem with returning a union is that you'll need to check for the type of the result every time you invoke the function.
So:
function isResponse(obj: IDetails | IResponse) obj is IResponse {
return obj && obj.response;
}
let value = myObj.response;
if (isResponse(value)) {
// value is IResponse
} else {
// value is IDetails
}
Another option is to simply not specify anything; the return types are automatically inferred:
the danger here is this allows you to return anything so there is no explicit guard, during development, against wrong return types.

Point.Empty.Equals(Point.Empty) == false // why?

Using NetTopologySuite, these expressions are false:
Point.Empty.Equals(Point.Empty); // false
Polygon.Empty.Equals(Polygon.Empty); // false
Debugging shows that this behavior is implemented by
// Geometry
public IntersectionMatrix Relate(IGeometry g)
{
return RelateOp.Relate(this, g); // Point.Empty, Point.Empty
}
// IntersectionMatrix
public bool IsEquals(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
{
if (dimensionOfGeometryA != dimensionOfGeometryB)
return false;
return IsTrue(_matrix[(int)Location.Interior, (int)Location.Interior]) &&
_matrix[(int)Location.Interior, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Boundary, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Interior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Boundary] == Dimension.False;
}
I wonder what the reason behind this is. Presumably this behavior occurs in related libraries (jts, GEOS) as well and I also assume there is a justification known by geo-algebra insiders. Can someone explain?

two way mapping

Is any way, how to create two classes, which will be referenced both way and will use only one FK? This interest me in One-to-One as like as One-to-Many cases.
f.e.:
Class First: Entity
{
Second second;
}
Class Second: Entity
{
First first;
}
String TwoWayReference()
{
First Fir = new First();
Second Sec = new Second();
Fir.second = Sec; // I need it is equivalent to: Sec.first = Fir;
if (Sec.first == Fir)
return "Is any way how to do this code works and code return this string?";
else
return "Or it is impossible?"
}
simplest would be
class First : Entity
{
private Second second;
public virtual Second Second
{
get { return this.second; }
set {
if (value != null)
{
value.First = this;
this.second = value;
}
}
}
}
class Second : Entity
{
private First first;
public virtual First First
{
get { return this.first; }
set {
if (value != null && value.Second != this)
{
value.Second = this;
this.first = value;
}
}
}
}