Ormlite int based enums coming as varchar(max) - servicestack

Can anyone tell me how to correctly get ORMLite to store enums as integers? I know that this was not supported in 2012 but i found code for some unit tests that suggest it should work now but it doesn't. When we try the column gets created as a varchar(max) in ms sql. We currently use a wrapping property that is ignored to convert the enum value to int but then you can't use it for queries etc so it is less than ideal.

Add a [Flags] attribute to enums you want ServiceStack to treat as integers.
From v4.0.54 you can also use the [EnumAsInt] attribute which will save the enum as an int in OrmLite but still serialize it as a string.

Related

JOOQ generator: use existing enums

I am using nu.studer.jooq gradle plugin to generate pojos, tables and records for a PostgreSQL database with tables that have fields of type ENUM.
We already have the enums in the application, so I would like that the generator uses those enums instead of generating new ones.
I defined in build.gradle for the generator: udts = false, so it doesn't generate the enums, and I wrote a custom generator strategy that sets the package for the enums to be the one of the already existing enums.
I have an issue in the generated table fields, the SQLDataType.VARCHAR.asEnumDataType(mypackage.ExistingEnum) doesn't work because the mypackage.ExistingEnum does not implement org.jooq.EnumType.
public enum ExistingEnum {
VAL1, VAL2
}
Generated table record:
public class EntryTable extends TableImpl<EntryRecord> {
public final TableField<EntryRecord, ExistingEnum> MY_FIELD = createField(DSL.name("my_field"), SQLDataType.VARCHAR.asEnumDataType(mypackage.ExistingEnum.class), this, "");
}
Is there something I can do to fix this issue? Also we have a lot of enums, so writing a converter for each of them is not suitable.
The point of having custom enum types is that they are individual types, independent of whatever you encode with your database enum types. As such, the jOOQ code generator cannot make any automated assumptions related to how to map the generated types to the custom types. You'll have to implement Converter types of some sort.
If you're not relying on the jOOQ provided EnumType types, you could use the <enumConverter/> configuration, or write implementations based on org.jooq.impl.EnumConverter, which help reduce boilerplate code.
If you have some conventions or rules how to map things a bit more automatically (just because jOOQ doesn't know your convention doesn't mean you don't know it either), you could implement a programmatic code generation configuration, where you query your dictionary views (e.g. PG_CATALOG.PG_ENUM) to generate ForcedType objects. You can even use jOOQ-meta for that purpose.

Golang levelDB struct

I'm trying to use following DB API: https://godoc.org/github.com/syndtr/goleveldb/leveldb#
(simple file based key/value DB)
I was able to put and get "key"s into the database.
However, I'm wondering if value can be a struct such as:
type Thm struct {
Name string
Age int
}
Then,
var Tmp Thm
Tmp.Name = "Gon"
Tmp.Age = 33
db.Put([]byte("test3"), []byte(Tmp), nil)
Right now, the error I'm getting is "cannot covert Tmp (type Thm) to type []byte.
If you have experiences with levelDB, could you help me how normally this will be done?
OR, should I convert struct into byte in order to make this work?
Thank you
levelDB only supports strings/byte arrays as keys and values. This is actually a pretty smart feature, because it keeps serialization of complex data structures at the application level. To serialize your Thm struct you can try the gob package if you don't need applications in other languages to be able to read the values, or protobufs, json, or msgpack if you need the serialized data to be accessible to other languages.

Mapping IQueryable class from Automapper

Does Automapper works with IQueryable?
I have 2 Query
IQueryable<V_ImageUpload> Query1;
IQueryable<V_ImageUpload> Query2;
Mapper.CreateMap<IQueryable<V_ImageUpload_WithReceiptBackup>, IQueryable<V_ImageUpload>>();
Query1 = Mapper.Map<IQueryable<V_ImageUpload_WithReceiptBackup>, IQueryable<V_ImageUpload>>(Query2);
Exception occured is:
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary
I've not used AutoMapper (so this was an excuse to try it out!), but there are queryable extensions available. Both your queryables are of the same type, so I'm not exactly sure what you are trying to achieve, but perhaps something like this is what you want, which takes an IQueryable<V_ImageUpload_WithReceiptBackup> and converts it to an IQueryable<V_ImageUpload>:
IQueryable<V_ImageUpload_WithReceiptBackup> query1;
IQueryable<V_ImageUpload> query2;
// Only map the actual type, not the queryable types
Mapper.CreateMap<V_ImageUpload_WithReceiptBackup, V_ImageUpload>();
query2 = query1.Project().To<V_ImageUpload>();
The .Project().To<V_ImageUpload>() keeps it as IQueryable, while Mapper.Map would end up with a List/IEnumerable. I only tested this out with LINQ to Objects, but hopefully it works with Entity Framework, or whatever you are using.

How to use BigDecimal in Xpages?

I'm using stored numeric values in calculations and matching situations and javascript doubles are a big "NO-NO" when doing these kind of operations.
However I can't find a solution on how to use java BigDecimal in SSJS in Xpages.
Since one should construct a BigDecimal using a string I have tried different approaches i SSJS. Whatever test the result is the same, the call is ambiguous:
Ambiguity when calling new java.math.BigDecimal(long) and new
java.math.BigDecimal(int)
How do I use a BigDecimal in my SSJS when values are stored in documents as Numbers?
How do I use BigDecimal with a string argument when values are stored in documents as Numbers?
edit/amend:
After accepting Svens answer I got a bit further and to my second question.
The value retrieved from the document is 451368 but it will be stored in variable as 451367.99999999994
How do I recover from that when the user should match against original value?
Use Java-Objects instead:
var value = new java.lang.Integer(1);
new java.math.BigDecimal(value);

How to auto-generate early bound properties for Entity specific (ie Local) Option Set text values?

After spending a year working with the Microsoft.Xrm.Sdk namespace, I just discovered yesterday the Entity.FormattedValues property contains the text value for Entity specific (ie Local) Option Set texts.
The reason I didn't discover it before, is there is no early bound method of getting the value. i.e. entity.new_myOptionSet is of type OptionSetValue which only contains the int value. You have to call entity.FormattedValues["new_myoptionset"] to get the string text value of the OptionSetValue.
Therefore, I'd like to get the crmsrvcutil to auto-generate a text property for local option sets. i.e. Along with Entity.new_myOptionSet being generated as it currently does, Entity.new_myOptionSetText would be generated as well.
I've looked into the Microsoft.Crm.Services.Utility.ICodeGenerationService, but that looks like it is mostly for specifying what CodeGenerationType something should be...
Is there a way supported way using CrmServiceUtil to add these properties, or am I better off writing a custom app that I can run that can generate these properties as a partial class to the auto-generated ones?
Edit - Example of the code that I would like to be generated
Currently, whenever I need to access the text value of a OptionSetValue, I use this code:
var textValue = OptionSetCache.GetText(service, entity, e => e.New_MyOptionSet);
The option set cache will use the entity.LogicalName, and the property expression to determine the name of the option set that I'm asking for. It will then query the SDK using the RetrieveAttriubteRequest, to get a list of the option set int and text values, which it then caches so it doesn't have to hit CRM again. It then looks up the int value of the New_MyOptionSet of the entity and cross references it with the cached list, to get the text value of the OptionSet.
Instead of doing all of that, I can just do this (assuming that the entity has been retrieved from the server, and not just populated client side):
var textValue = entity.FormattedValues["new_myoptionset"];
but the "new_myoptionset" is no longer early bound. I would like the early bound entity classes that gets generated to also generate an extra "Text" property for OptionSetValue properties that calls the above line, so my entity would have this added to it:
public string New_MyOptionSetText {
return this.GetFormattedAttributeValue("new_myoptionset"); // this is a protected method on the Entity class itself...
}
Could you utilize the CrmServiceUtil extension that will generate enums for your OptionSets and then add your new_myOptionSetText property to a partial class that compares the int value to the enums and returns the enum string
Again, I think specifically for this case, getting CrmSvcUtil.exe to generate the code you want is a great idea, but more generally, you can access the property name via reflection using an approach similar to the accepted answer # workarounds for nameof() operator in C#: typesafe databinding.
var textValue = entity.FormattedValues["new_myoptionset"];
// becomes
var textValue = entity.FormattedValues
[
// renamed the class from Nameof to NameOf
NameOf(Xrm.MyEntity).Property(x => x.new_MyOptionSet).ToLower()
];
The latest version of the CRM Early Bound Generator includes a Fields struct that that contains the field names. This allows accessing the FormattedValues to be as simple as this:
var textValue = entity.FormattedValues[MyEntity.Fields.new_MyOptionSet];
You could create a new property via an interface for the CrmSvcUtil, but that's a lot of work for a fairly simple call, and I don't think it justifies creating additional properties.

Resources