The requirement is to store the hardcoded value for varchar which is in an entity file(.eti). I tried adding to the default option but it is not reflecting.
Default option works well with boolean values (true/false), typelists (you can choose a default typecode), monetary amounts too, but it looks like it is not allowed to specify a default varchar.
Therefore the easiest way would be to create a preupdate rule which inserts that default value every time when you create a new record in the database.
Preupdate rule example:
#gw.rules.RuleName("YourEntityAssignDefaultValue")
internal class YourEntityAssignDefaultValueRule {
static function doCondition(yourEntity : entity.YourEntity) : boolean {
return yourEntity.New
}
static function doAction(yourEntity : entity.YourEntity, actions : gw.rules.Action) {
yourEntity.yourColumn = "defaultValue"
}
}
you can achieve through getter and setter properties in an appropriate enhancement class.
public property get PolicyNumber(): String {
return this.PolicyNumber }
and somewhere class you must be assigned the value to the PolicyNumber field then it will reflect.
Related
I have the following value object code which validates CustCode by some expensive database operations.
public class CustCode : ValueObject<CustCode>
{
private CustCode(string code) { Value = code; }
public static Result<CustCode> Create(string code)
{
if (string.IsNullOrWhiteSpace(code))
return Result.Failure<CustCode>("Code should not be empty");
// validate if the value is still valid against the database. Expensive and slow
if (!ValidateDB(code)) // Or web api calls
return Result.Failure<CustCode>("Database validation failed.");
return Result.Success<CustCode>(new CustCode(code));
}
public string Value { get; }
// other methods omitted ...
}
public class MyEntity
{
CustCode CustCode { get; }
....
It works fine when there is only one or a few entity instances with the type. However, it becomes very slow for method like GetAll() which returns a lot of entities with the type.
public async IAsyncEnumerable<MyEntity> GetAll()
{
string line;
using var sr = File.OpenText(_config.FileName);
while ((line = await sr.ReadLineAsync()) != null)
{
yield return new MyEntity(CustCode.Create(line).Value); // CustCode.Create called many times
}
}
Since data in the file was already validated before saving so it's actually not necessary to be validated again. Should another Create function which doesn't validate the value to be created? What's the DDD idiomatically way to do this?
I generally attempt not to have the domain call out to retrieve any additional data. Everything the domain needs to do its job should be passed in.
Since value objects represent immutable state it stands to reason that once it has managed to be created the values are fine. To this end perhaps the initial database validation can be performed in the integration/application "layer" and then the CustCode is created using only the value(s) provided.
Just wanted to add an additional point to #Eben Roux answer:
In many cases the validation result from a database query is dependent on when you run the query.
For example when you want to check if a phone number exists or if some product is in stock. The answers to those querys can change any second, and though are not suited to allow or prevent the creation of a value object.
You may create a "valid" object, that is (unknowingly) becoming invalid in the very next second (or the other way around). So why bother running an expensive validation, if the validation result is not reliable.
I am using the Interface IOptions in Core 2.0:
public interface IOptions<out TOptions> where TOptions : class, new()
And in my Startup.cs I can wire it up,
// Example #1: Basic options
// Register the ConfigurationBuilder instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);
private readonly MyOptions _options;
_options = optionsAccessor.Value;
What I want to know is how does the Framework know what Value is supposed to be? Where is "Value" assigned? It's not the same as value in a property, it appears. Here Value is a whole class reference.
For checking the depth implementation of Options, you could download Options, and debug the project.
how does the Framework know what Value is supposed to be?
While you configure the Options, you have passed the type by services.Configure<MyOptions>(Configuration) , the MyOptions will passed into generic type TOptions.
It's not the same as value in a property, it appears. Here Value is a whole class reference.
Tha Value is TOptions type which is returned by OptionsManager.
public TOptions Value
{
get
{
return Get(Options.DefaultName);
}
}
Where is "Value" assigned?
Value will be configured by ConfigureNamedOptions and created by OptionsFactory, then you could access it by OptionsManager.
I am using Azure table storage and have questions about how nulls and default values for entities work.
Specifically, I have a class that extends TableServiceEntity. The default constructor for this class is setting default values for various properties like so:
public class MyEntity: TableServiceEntry
{
public MyEntity() : MyEntity("invalid", "invalid") {}
public MyEntity(string f1, string f2)
{
Field1 = f1;
Field2 = f2;
}
public string Field1 { get; set; }
public string Field2 { get; set; }
}
I tested this class locally (on the emulator) by constructing the following entity:
MyEntity e = new MyEntity("hello", null);
I uploaded the entity and then retrieved it locally and the two fields were set to "hello" and null, respectively, as expected.
However, when I uploaded the same entity to the Azure cloud, what I received back was "hello" and "invalid", respectively, for the two properties.
My code that saves the entity is below:
public class MyTable : TableServiceContext
{
...
public void AddEntry(MyEntity e)
{
this.AddObject("MyTable", e);
this.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);
}
}
I was able to fix this by making the default constructor take no arguments, but now I feel like I have a fundamental misunderstanding of how table storage works. Is it true that when you specify defaults for properties of a TableServiceEntry, those become the defaults for each row in the table in the cloud but not in the emulator (i.e. cloud vs. SQL Express)? If so, why can't I override those defaults with null in the cloud? Is there any documentation that explains how default constructors and nulls work in Azure table storage?
Yes, there is a difference between how table storage behaves in the emulator and in the cloud. The emulator implemented in SQL server, returns all columns defined for a table, even if not defined for a row, irrespective of the columns value (null / non-null). In the cloud, a property set to null is neither stored nor returned in the REST call.
A quick fix would be to check for null in property set, and only mutate the property if the value passed in, is not null.
Devstorage and real storage behave differently in some cases, but I've never seen them handle NULL values differently. And I've certainly never seen it change a value from NULL to "invalid", as you seem to be implying. Are you sure you didn't accidentally upload the wrong values to the cloud? You may want to try again, and use Fiddler to look at the actual request and response values.
In jcouchdb I used to extend BaseDocument and then, in a transparent manner, mix Annotations and not declared fields.
Example:
import org.jcouchdb.document.BaseDocument;
public class SiteDocument extends BaseDocument {
private String site;
#org.svenson.JSONProperty(value = "site", ignoreIfNull = true)
public String getSite() {
return site;
}
public void setSite(String name) {
site = name;
}
}
and then use it:
// Create a SiteDocument
SiteDocument site2 = new SiteDocument();
site2.setProperty("site", "http://www.starckoverflow.com/index.html");
// Set value using setSite
site2.setSite("www.stackoverflow.com");
// and using setProperty
site2.setProperty("description", "Questions & Answers");
db.createOrUpdateDocument(site2);
Where I use both a document field (site) that is defined via annotation and a property field (description) not defined, both get serialized when I save document.
This is convenient for me since I can work with semi-structured documents.
When I try to do the same with Ektorp I have documents using annotations and Documents using HashMap BUT I couldn't find an easy way of getting the mix of both (I've tried using my own serializers but this seems to much work for something that I get for free in jcouchdb). Also tried to annotate a HashMap field but then is serialized as an object and I get the fields automatically saved BUT inside an object with the name of the HashMap field.
Is it possible to do (easily/for free) using Ektorp?
It is definitely possible. You have two options:
Base your class on org.ektorp.support.OpenCouchDbDocument
Annotate the you class with #JsonAnySetter and #JsonAnyGetter. Red more here: http://wiki.fasterxml.com/JacksonFeatureAnyGetter
I am currently using CSS to change everything I write to upperCase when I create an entry, but that is not enough. When I save things, the text shown in the text fields is upper case, but the real value that Grails stores stays in lower case.
I am assuming I'd need to change something in the controller or anything.
Maybe transforming the $fieldValue CSS could work??
Any ideas would help!
Thnks!
You could just write setters for your domain object?
class Domain {
String aField
void setAField( String s ){
aField = s?.toUpperCase()
}
}
I think you are asking how to change values on your domain objects to uppercase. If this is not the case please clarify the question.
You have a bunch of options. I would recommend
1) In a service method, before you save, using String.toUpperCase() to modify the appropriate values on the domain object.
or
2) You can use the underlying Hibernate interceptors by defining a beforeInsert method on your domain object, and doing the toUpperCase there. (see 5.5.1 of the grails documentation)
or
3) You could do this client side. However, if it is a "business requirement" that the values are stored as upper, then I recommend doing the translation server side. It is easier to wrap tests around that code....
Using annotations is cleanest approach
import org.grails.databinding.BindingFormat
class Person {
#BindingFormat('UPPERCASE')
String someUpperCaseString
#BindingFormat('LOWERCASE')
String someLowerCaseString
}
Here is link for it: Grails doc for data binding
You can use Groovy metaprogramming to change the setter for all domain class String-typed properties without actually writing a custom setter for each property.
To do this, add something like the following to the init closure of Bootstrap.groovy
def init = { servletContext ->
for (dc in grailsApplication.domainClasses) {
dc.class.metaClass.setProperty = { String name, value ->
def metaProperty = delegate.class.metaClass.getMetaProperty(name)
if (metaProperty) {
// change the property value to uppercase if it's a String property
if (value && metaProperty.type == String) {
value = value.toUpperCase()
}
metaProperty.setProperty(delegate, value)
} else {
throw new MissingPropertyException(name, delegate.class)
}
}
}
}