Strange behaviour

Oct 8, 2008 at 1:07 PM
Edited Oct 8, 2008 at 2:00 PM
Here some code:

[TypeStorage(TableName = "tbArticle")]
public class Article : Retina.Entity
{
    [FieldStorage(ColumnName = "ArticleGuid", IsKey = true, IsIdentity = true, IdGeneratorType = typeof(IdGeneratorGuid))]
    private Guid m_ArticleGuid;

    [FieldStorage(ColumnName = "Name")]
    private string m_Name;

    public Article() { }

    public static Expression ByName(string pName)
    {
        return new Expression(
            typeof(Article), GetField(typeof(Article), "m_Name"), Criteria.Equal, pName);
    }
}

I can specify the ColumnName of the m_Name field? "Name" ?

And how to check if the Entity is valid (no broken constraint) before performing persistance? Entity.IsValid() does not do that. I've created an entity object that doesn't respect a client constraint and .IsValid is 'true'.

Thanks.
Oct 8, 2008 at 4:09 PM
Ok, I've found a tip. I set the FieldStorage flag on the accessors:

[TypeStorage(TableName = "tbArticle")]
public class Article : Retina.Entity
{
    private Guid m_ArticleGuid;

    [FieldStorage(ColumnName = "ArticleGuid", IsKey = true, IsIdentity = true, IdGeneratorType = typeof(IdGeneratorGuid))]
    public Guid ArticleGuid { get { return m_ArticleGuid; } set { m_ArticleGuid = value; } }

    private string m_Name;

    [FieldStorage(ColumnName = "Name")]
    public string Name { get { return m_Name; } set { m_Name = value; } }

    public Article() { }

    public static Expression ByName(string pName)
    {
        return new Expression(
            typeof(Article), GetField(typeof(Article), "Name"), Criteria.Equal, pName);
    }
}
Coordinator
Oct 9, 2008 at 12:39 AM
Hi, this is the intended behavior. All Criteria field name MUST reference entity field names, not column (storage) names.
All ORMs I know (at least the good ones...) works this way and the idea is to generate code that's agnostic from the storage implementation details.
LINQ and its ORM providers (LINQ to SQL & LINQ to Entities) also work this way.
This is also in tune with MS design recommendations about using public accesors for entities (and classes in general).

Best regards,
Andrés.
Oct 9, 2008 at 10:09 AM
Thanks for your feedback.

I have another behaviour I don't understand.

I've defined a Entity ClientContraint:

private IConstraintResult IsClientRefOk(object appContext)
{
    if (ClientRef == null || !new Regex("^[A-Z]{3}[0-9]{3}$").IsMatch(ClientRef))
    {
        return new BrokenConstraint("ClientRef NOK");
    }

    return new HeldConstraint("ClientRef OK");
}

Main code:

Order falseOrder = new Order();

falseOrder.ClientRef = "12345"; /* Wrong clientRef here */

if (falseOrder.IsValid) /* Is 'true'... */
{
    falseOrder = broker.Persist(falseOrder) as Order;
}

IsValid is not based on the defined constraints?

And another point: I haven't found attribute to set the max length of a string field.

Thanks!
Coordinator
Oct 9, 2008 at 8:18 PM
So far Retina has two different and unrelated (so far) validation mechanisms, and you are hitting just the case where those still not work together.

The client validations using constraints is the older validation mechanism,  and to use it you must run the entity through the Validate method found in the ObjectContext high level API class.

The IsValid property is a new validation scheme being tested based on special attributes (derived from the excellent EViL validation library) and to make it work you need to add attributes to each field/property to validate.
If you want to use some of this validation attributes please look within the "Retina.Validation" namespace.

Please take into account that this new validation engine is not yet integrated in the persistence pipeline, so no validation will be performed using this engine before any persistence operation.

Regarding the max lenght (and some other) colum attributes you need to add a dataType specific attribute to the field/property.
For example, if you have a String property, in order to limit the lenght of the column you need to define an attribute like this:

[

FieldStorage("Description")]
[
StringDataType(1, 255)]
public virtual string Description{get; set;}

This sets the minimum lenght to 1, and maximum lenght to 255 ANSI characters.
Retina also allow you to define UNICODE (NVarchar) or TEXT (and NTEXT) storage columns.
Please look into the different contructors & properties in the dataType attributes.

If you don't specify a dataType attribute, Retina will infer it from the type of the property, but using default values for all those special properties.

Retina supports the use of NULLABLE properties using the standard Nullable<> class (or C# ? type modifier) for all value types, and for reference types like string you need to provide a [NullableStringDataType] attribute.

Best regards,
Andrés.

 

Oct 9, 2008 at 8:52 PM
Edited Oct 11, 2008 at 7:14 AM
Thanks for this explanation.

I am now having a look to the Test project. I've compiled the latest source and will add my one test-project to test Retina.NET (to enter inside the Core source with the debugger :)).

One word, thanks a lot for this M/OR, it is really appreciated here.
Coordinator
Oct 11, 2008 at 3:08 AM
Thank you for your kind words, I really make a significative effort to make Retina.NET a viable & usefull product.
I'm using it myself on several projects and so far I'm very satisfied.

I will try to refresh a little the Quick Start document and upload the latest version to CodePlex during the next days.
Stay tuned.

Again, thanks,
Andrés.