Show / Hide Table of Contents

    Property Attributes

    You use properties attributes to define the metadata that the Mapper requires. For example, given this very simple model class:

    using System;
    
    public class Subscriber
    {
        public int SubscriberId { get; set; }
    
        public string Name { get; set; }
    
        public DateTime Expiration { get; set; }
    }
    

    Adding mapping attributes to this class provides the metadata to automatically map these properties to stored procedures or SQL statements:

    • SQL Server
    • PostgreSQL
    using System;
    using ArgentSea.Sql;
    
    public class Subscriber
    {
        [MapToSqlInt("@SubID", true)]
        public int SubscriberId { get; set; }
    
        [MapToSqlNVarChar("@SubscriberName", 255)]
        public string Name { get; set; }
    
        [MapToSqlDateTime2("@EndDate")]
        public DateTime Expiration { get; set; }
    }
    
    Note

    The “@” parameter prefix is optional — ArgentSea will always add the “@” automatically for parameters and remove it automatically when reading data reader rows.

    using System;
    using ArgentSea.Pg;
    
    public class Subscriber
    {
        [MapToPgInteger("SubId", true)]
        public int SubscriberId { get; set; }
    
        [MapToPgVarchar("SubscriberName", 255)]
        public string Name { get; set; }
    
        [MapToPgTimestamp("EndDate")]
        public DateTime Expiration { get; set; }
    }
    
    Note

    ArgentSea will automatically convert the casing of parameter names and column names to lowercase.

    Often, due to different naming conventions or development drift, database column names and the corresponding .NET properties names do not match. That is why every attribute requires a “name” argument — which should correspond to the database name. The Mapper will create query parameters and reference DataReader columns based on this name.

    Important

    Database parameters and columns should be named as consistently as possible. In most cases, this means the parameters have the same name as the columns they reference. If you like to use varying parameter names or alias columns in your result, you will find the Mapper unhelpful.

    Properties without a mapping attribute are simply ignored.

    Attribute Types

    A mapping attribute is defined for most common database types. Attributes for spatial data types, CLR types, XML, and JSON types (for example) are missing because there is no straightforward mapping between the core .NET base types and these database types. ArgentSea supports writing a custom handler to render any of these complex types; such work is no more difficult than writing the same processing in ADO.NET.

    The attribute itself defines the underlying database type. Naturally, the attribute type and the property type must match. For example, a long (Int64) property must map to a bigint database type. The Mapper will throw an error if these types do not match. There is no attempt to cast data to a different type, even if the cast would be successful.

    Many data attribute types have an additional parameters. The length argument, for example, on string and array types, helps optimize data access performance by ensuring that buffers are sized appropriately.

    Here is catalog of the current attributes, along with their arguments and corresponding .NET types:

    • SQL Server
    • PostgreSQL
    Attribute Arguments .NET types SqlType
    MapToSqlNVarCharAttribute length¹ String, Enum², Nullable<Enum> NVarChar
    MapToSqlNCharAttribute length String, Enum², Nullable<Enum> NChar
    MapToSqlVarCharAttribute length¹, localeid³ String, Enum², Nullable<Enum> VarChar
    MapToSqlCharAttribute length, localeid³ String, Enum², Nullable<Enum> Char
    MapToSqlBigIntAttribute Int64, Enum⁴, Nullable<Int64>, Nullable<Enum> BigInt
    MapToSqlIntAttribute Int32, Enum⁴, Nullable<Int32>, Nullable<Enum> Int
    MapToSqlSmallIntAttribute Int16, Enum⁴, Nullable<Int16>, Nullable<Enum> SmallInt
    MapToSqlTinyIntAttribute Byte, Enum⁴, Nullable<Byte>, Nullable<Enum> TinyInt
    MapToSqlBitAttribute Boolean, Nullable<Boolean> Bit
    MapToSqlDecimalAttribute precision, scale Decimal, Nullable<Decimal> Decimal
    MapToSqlMoneyAttribute Decimal, Nullable<Decimal> Money
    MapToSqlSmallMoneyAttribute Decimal, Nullable<Decimal> SmallMoney
    MapToSqlFloatAttribute Double, Nullable<Double> Float
    MapToSqlRealAttribute Float, Nullable<Float> Real
    MapToSqlDateTimeAttribute DateTime, Nullable<DateTime> DateTime
    MapToSqlDateTime2Attribute precision DateTime, Nullable<DateTime> DateTime2
    MapToSqlDateAttribute DateTime, Nullable<DateTime> Date
    MapToSqlTimeAttribute TimeSpan, Nullable<TimeSpan> Time
    MapToSqlDateTimeOffsetAttribute DateTimeOffset, Nullable<DateTimeOffset> DateTimeOffset
    MapToSqlVarBinaryAttribute length¹ byte[] VarBinary
    MapToSqlBinaryAttribute length byte[] Binary
    MapToSqlUniqueIdentifierAttribute Guid, Nullable<Guid> UniqueIdentifier

    ¹ For “max” values (nvarchar(max), varbinary(max), etc.) use length of -1.

    ² The Enum name is saved as string.

    ³ Locale Id is the Ansi code page to use for Unicode conversion. For en-US locale, for example, use 1033.

    ⁴ The Enum value is saved based on its underlying numeric value. The Enum integer base type (int, short, byte, etc.) must match the database type.

    Attribute Arguments .NET types SQL Type
    MapToPgVarcharAttribute length String, Enum¹, Nullable<Enum> VarChar
    MapToPgCharAttribute length String, Enum¹, Nullable<Enum> Char
    MapToPgTextAttribute String, Enum¹, Nullable<Enum> VarChar
    MapToPgBigintAttribute Int64, Enum², Nullable<Int64>, Nullable<Enum> Bigint
    MapToPgIntegerAttribute Int32, Enum², Nullable<Int32>, Nullable<Enum> Integer
    MapToPgSmallintAttribute Int16, Enum², Nullable<Int16>, Nullable<Enum> Smallint
    MapToPgInternalCharAttribute Byte, Enum², Nullable<Byte>, Nullable<Enum> (Internal) "char"³
    MapToPgBooleanAttribute Boolean, Nullable<Boolean> Boolean
    MapToPgNumericAttribute precision, scale Decimal, Nullable<Decimal> Numeric
    MapToPgMoneyAttribute Decimal, Nullable<Decimal> Money
    MapToPgDoubleAttribute Double, Nullable<Double> Double
    MapToPgRealAttribute Float, Nullable<Float> Real
    MapToPgTimestampAttribute DateTime, DateTimeOffset, Nullable<DateTime>, Nullable<DateTimeOffset> Timestamp
    MapToPgTimestampTzAttribute DateTimeOffset, Nullable<DateTimeOffset> TimestampTz
    MapToPgDateAttribute DateTime, Nullable<DateTime> Date
    MapToPgTimeAttribute TimeSpan, Nullable<TimeSpan> Time
    MapToPgIntervalAttribute TimeSpan, Nullable<TimeSpan> Interval
    MapToPgTimeTzAttribute TimeSpan, DateTimeOffset, Nullable<TimeSpan>, Nullable<DateTimeOffset> TimeTz
    MapToPgArrayAttribute Array Array
    MapToPgByteaAttribute length byte[] Bytea
    MapToPgArrayAttribute NpgsqlType T[]⁴ Array
    MapToPgHstoreAttribute length IDictionary<string, string> Hstore
    MapToPgUuidAttribute Guid, Nullable<Guid> UniqueIdentifier

    ¹ The Enum name is saved as string.

    ² The Enum value is saved based on its underlying numeric value. The Enum integer base type (int, short, etc.) must match the database type.

    ³ This data type is not intended for general use.

    ⁴ The Npgsql type is used to create parameters; the Property type is used to read them.

    Required

    Finally, the the data attributes have an optional required (sic) parameter. If a database field is DbNull, the Mapper will normally set the corresponding property to null. However, the missing value may represent an entirely absent record. In this case, the correct result is a null object, not a valid instance with null/default properties. Setting a property attribute’s required argument to True causes the Mapper to return a null object if the property would be null. By default (if not specified), required is false.

    Handling Nulls and Empty Types

    Because the Mapper is handling database values, there is generally a possibility that the database value is DbNull. How this is converted to a .NET type depends upon the type.

    Strings and Arrays

    A .NET string with a value of null or a null array will be saved as a DbNull. Empty strings will save as a zero-length string.

    Integers

    Integers cannot be null, so the advent of nullable types is a godsend for mapping to database storage. To save or retrieve an integer (byte, Int16, Int32, or Int64) database value from a column that allows null, you should declare a nullable value type.

    Floating Point Numbers

    Like integer types, floating point types (Double and Float) can be wrapped in a nullable value. However, ArgentSea also handles NaN as a DbNull. If the floating point value is presented as a nullable type, then ArgentSea will save or retrieve NaN; if floating point type is presented, then NaN will be converted to/from a DbNull.

    Guids

    Rather like floating point types, Guid.Empty (00000000-0000-0000-0000-000000000000) will be converted to a data DbNull when read from or written to the database. Also like floats, if you need to write an empty Guid value, wrap it in a nullable type.

    Enum Types

    .NET enum values can be stored as either numbers or strings. Writing to a text column will automatically save the name of the enum; writing to a numeric column saves the number value.

    Warning

    Enums can inherit from several base types (byte, short, int, etc.). If you are saving to a numeric database column, the base type must correctly correspond to the database data type. Enums are Int32 by default.

    Nullable Enum types will read or write as a DbNull when the value is null.

    Model Inheritance

    Models which inherit from other Model classes also inherit the attributes of the parent class. This can be very useful when some queries return a subset of the data entities overall columns.

    Properties with Object Types

    This page has described simple 1:1 mapping between database columns and model properties. This is the heart of the Mapper. However, mapping sometimes requires more complex types, built from these simple relationships.

    In addition to the types already described, the Mapper supports three additional types of Model properties:

    • Properties which contain a second Model class
    • Properties which contain lists of Model classes
    • Sharded record identifiers

    These will be explored in the next section.

    Next: Complex Attributes

    • Improve this Doc
    Back to top Generated by DocFX