2

I am building EF Code first POCOs that'll be used between an Oracle back-end and a MS SQL Server backend. I'm having a problem finding the right way to tackle a Timestamp property that'll work on either database back-end.

MS SQL Server would have me use a common property like this:

[Timestamp]
public byte[] Timestamp {get;set;}

And then in the fluent mapping it would look like this

map.Property(p => p.Timestamp).IsRowVersion();

However Oracle would have me change my common property type to this:

public int Timestamp {get;set;}

And then in the fluent mapping it would look like this

map.Property(p => p.Timestamp).HasColumnName("ORA_ROWSCN").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).IsConcurrencyToken();

So my first guess was maybe I could change the data type to long, since timestamp is eight bytes, but SqlServer didn't like the mapping.

My next guess is to give up on Timestamp and Ora_RowScn and make up my own Optimistic Concurrency property. Any suggestions or know if a way to have a happy model that works between both Sql and Oracle? Thanks.

1 Answer 1

1

This is how I resolved the issue. I got rid of the [Timestamp] attribute. Then I also created two assemblies for my repositories, one for Oracle and the other for MSSQL. Then my base model looks like this.

[DataContract]
    public abstract class DomainBase
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        [DataMember]
        [Key]
        public long Id { get; set; }


        private byte[] _timestamp=new Guid().ToByteArray();

        /// <summary>
        /// Gets or sets the timestamp.
        /// </summary>
        [DataMember]
        public byte[] Timestamp { get { return _timestamp; }
            set { _timestamp = value;
            if (_timestamp != null && _signature != Convert.ToBase64String(_timestamp))
                    _signature = Convert.ToBase64String(_timestamp);
            }
        }

        private string _signature = Convert.ToBase64String(new Guid().ToByteArray());

        /// <summary>
        /// Gets the signature.
        /// </summary>
        [DataMember]
        public string Signature
        {
            get { return _signature ?? (Timestamp != null ? _signature = Convert.ToBase64String(Timestamp) : null); }
            protected set { _signature = value;
                if ((_timestamp == null && !String.IsNullOrWhiteSpace(_signature)) ||
                    (_timestamp != null && !String.IsNullOrWhiteSpace(_signature) && Convert.ToBase64String(_timestamp) != _signature))
                    _timestamp = Convert.FromBase64String(value);
            }
        }

        /// <summary>
        /// Gets a value indicating whether has signature.
        /// </summary>
        public bool HasSignature
        {
            get { return Timestamp != null; }
        }
    }

Then this is how I handle the mappings in each fluent setup.

For MSSQL Server.

Property(p => p.Timestamp).HasColumnType("timestamp").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).IsRowVersion();
            Ignore(p => p.Signature);

For Oracle

Ignore(p => p.Timestamp);
            Property(p => p.Signature).HasColumnName("Timestamp").IsConcurrencyToken();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.