/// <summary>Registers DB sequences. </summary> /// <param name="name">Sequence name.</param> /// <param name="type">Data type, optional. If null, 64-bit integer is assumed.</param> /// <param name="startValue">Optional, assumed zero if missing.</param> /// <param name="increment">Optional, assumed 1 if missing.</param> /// <param name="explicitSchema">Optional, explicit schema. If missing, sequence schema is assigned from module's area.</param> public void RegisterSequence(string name, Type type = null, int startValue = 0, int increment = 1, string explicitSchema = null) { type = type ?? typeof(long); var sequence = new SequenceDefinition(this, name, type, startValue, increment, explicitSchema); Sequences.Add(sequence); }
public static T GetSequenceNextValue <T>(this IEntitySession session, SequenceDefinition sequence) where T : struct { Util.Check(sequence != null, "Sequence parameter may not be null."); Util.Check(typeof(T) == sequence.DataType, "Requested next value type {0} does not match sequence {1} data type (2}.", typeof(T), sequence.Name, sequence.DataType); var ds = session.Context.App.DataAccess.GetDataSource(session.Context); var db = ds.Database; var entSession = (EntitySession)session; var v = db.GetSequenceNextValue(entSession, sequence); if (v.GetType() == typeof(T)) { return((T)v); } //Postgres - all sequences are int64, so we need to convert here return((T)ConvertHelper.ChangeType(v, typeof(T))); }
public override void ApplyOnMember(EntityModelBuilder builder) { HostMember.Flags |= EntityMemberFlags.AutoValue; HostMember.AutoValueType = this.Type; switch (this.Type) { case AutoType.Identity: HostEntity.Flags |= EntityFlags.HasIdentity; HostEntity.IdentityMember = HostMember; base.HostMember.Flags |= EntityMemberFlags.Identity | EntityMemberFlags.NoDbInsert | EntityMemberFlags.NoDbUpdate; //Usually identity is int (or long). But there are some wierd real-life databases with Numeric (Decimal) identity columns // apparently MS SQL allows this var intOrDec = base.HostMember.DataType.IsInt() || base.HostMember.DataType == typeof(Decimal); if (!intOrDec) { builder.Log.Error("Entity member {0}.{1}, type {2}: Identity attribute may be set only on member of integer or decimal types. ", HostEntity, base.HostMember.MemberName, this.Type); return; } HostEntity.Events.New += EntityEvent_NewEntityHandleIdentity; HostEntity.SaveEvents.SubmittedChanges += EntityEvent_IdentityEntitySubmitted; break; case AutoType.Sequence: if (!base.HostMember.DataType.IsInt()) { builder.Log.Error("Entity member {0}.{1}, type {2}: Sequence attribute may be set only on member of integer types. ", HostEntity, HostMember.MemberName, this.Type); return; } if (string.IsNullOrWhiteSpace(this.SequenceName)) { builder.Log.Error("Entity member {0}.{1}: Sequence name must be specified.", HostEntity, HostMember.MemberName); return; } _sequence = builder.Model.FindSequence(this.SequenceName, HostEntity.Module); if (_sequence == null) { builder.Log.Error("Entity member {0}.{1}: Sequence {0} not defined.", HostEntity, HostMember.MemberName, this.SequenceName); return; } if (_sequence.DataType != base.HostMember.DataType) { builder.Log.Error("Entity member {0}.{1}: data type {2} does not match sequence '{3}' data type {4}.", HostEntity, HostMember.MemberName, HostMember.DataType, this.SequenceName, _sequence.DataType); return; } HostEntity.Events.New += EntityEvent_NewEntityHandleSequence; break; case AutoType.NewGuid: if (!CheckDataType(builder, typeof(Guid))) { builder.Log.Error("Entity member {0}.{1}: Auto attribute with AutoType=NewGuid must be on Guid-type member.", HostEntity, HostMember.MemberName); return; } HostEntity.Events.New += EntityEvent_HandleNewGuid; break; case AutoType.CreatedOn: case AutoType.UpdatedOn: if (!CheckDataType(builder, typeof(DateTime), typeof(DateTime?))) { return; } if (this.Type == AutoType.CreatedOn) { base.HostMember.Flags |= EntityMemberFlags.NoDbUpdate; } HostEntity.SaveEvents.SavingChanges += EntityEvent_HandleCreatedUpdatedOnDateTime; break; case AutoType.CreatedBy: if (!CheckDataType(builder, typeof(string))) { return; } HostEntity.Events.New += EntityEvent_HandleUpdatedCreatedBy; base.HostMember.Flags |= EntityMemberFlags.NoDbUpdate; break; case AutoType.UpdatedBy: if (!CheckDataType(builder, typeof(string))) { return; } HostEntity.Events.New += EntityEvent_HandleUpdatedCreatedBy; HostEntity.Events.Modified += EntityEvent_HandleUpdatedCreatedBy; break; case AutoType.CreatedById: if (!CheckDataType(builder, typeof(Guid), typeof(int))) { return; } HostEntity.Events.New += EntityEvent_HandleUpdatedCreatedById; base.HostMember.Flags |= EntityMemberFlags.NoDbUpdate; break; case AutoType.UpdatedById: if (!CheckDataType(builder, typeof(Guid), typeof(int))) { return; } HostEntity.Events.New += EntityEvent_HandleUpdatedCreatedById; HostEntity.Events.Modified += EntityEvent_HandleUpdatedCreatedById; break; case AutoType.TransIdCreated: if (!CheckDataType(builder, typeof(Guid))) { return; } HostEntity.Events.New += HandleCreatedUpdatedInTransId; HostMember.Flags |= EntityMemberFlags.NoDbUpdate; break; case AutoType.TransIdUpdated: if (!CheckDataType(builder, typeof(Guid))) { return; } HostEntity.Events.New += HandleCreatedUpdatedInTransId; HostEntity.Events.Modified += HandleCreatedUpdatedInTransId; break; case AutoType.RowVersion: HostEntity.RowVersionMember = base.HostMember; base.HostMember.Flags |= EntityMemberFlags.RowVersion | EntityMemberFlags.NoDbInsert | EntityMemberFlags.NoDbUpdate; base.HostEntity.Flags |= EntityFlags.HasRowVersion; base.HostMember.ExplicitDbTypeSpec = "rowversion"; break; }//swith AutoValueType }
public override void Apply(AttributeContext context, Attribute attribute, EntityMemberInfo member) { _member = member; var entity = member.Entity; member.Flags |= EntityMemberFlags.AutoValue; member.AutoValueType = this.Type; switch (this.Type) { case AutoType.Identity: entity.Flags |= EntityFlags.HasIdentity; member.Flags |= EntityMemberFlags.Identity | EntityMemberFlags.NoDbInsert | EntityMemberFlags.NoDbUpdate; //Usually identity is int (or long). But there are some wierd real-life databases with Numeric (Decimal) identity columns // apparently MS SQL allows this var intOrDec = member.DataType.IsInt() || member.DataType == typeof(Decimal); if (!intOrDec) { context.Log.Error("Entity member {0}.{1}, type {2}: Identity attribute may be set only on member of integer or decimal types. ", _member.Entity, _member.MemberName, this.Type); return; } entity.Events.New += EntityEvent_NewEntityHandleIdentity; // Mark all entities referencing This entity with ReferencesIdentity flag foreach (var mr in entity.IncomingReferences) { mr.Entity.Flags |= EntityFlags.ReferencesIdentity; } break; case AutoType.Sequence: if (!member.DataType.IsInt()) { context.Log.Error("Entity member {0}.{1}, type {2}: Sequence attribute may be set only on member of integer types. ", _member.Entity, _member.MemberName, this.Type); return; } if (string.IsNullOrWhiteSpace(SequenceName)) { context.Log.Error("Entity member {0}.{1}: Sequence name must be specified.", _member.Entity, _member.MemberName); return; } _sequence = context.Model.FindSequence(SequenceName, entity.Module); if (_sequence == null) { context.Log.Error("Entity member {0}.{1}: Sequence {0} not defined.", _member.Entity, _member.MemberName, this.SequenceName); return; } if (_sequence.DataType != member.DataType) { context.Log.Error("Entity member {0}.{1}: data type {2} does not match sequence '{3}' data type {4}.", _member.Entity, _member.MemberName, _member.DataType, this.SequenceName, _sequence.DataType); return; } entity.Events.New += EntityEvent_NewEntityHandleSequence; break; case AutoType.NewGuid: if (!CheckDataType(context, typeof(Guid))) { return; } entity.Events.New += EntityEvent_HandleNewGuid; break; case AutoType.CreatedOn: case AutoType.UpdatedOn: if (!CheckDataType(context, typeof(DateTime), typeof(DateTimeOffset))) { return; } if (this.Type == AutoType.CreatedOn) { member.Flags |= EntityMemberFlags.NoDbUpdate; } if (member.DataType == typeof(DateTime) || member.DataType == typeof(DateTime?)) { entity.SaveEvents.SavingChanges += EntityEvent_HandleCreatedUpdatedOnDateTime; } else { entity.SaveEvents.SavingChanges += EntityEvent_HandleCreatedUpdatedOnDateTimeOffset; } break; case AutoType.CreatedBy: if (!CheckDataType(context, typeof(string))) { return; } entity.Events.New += EntityEvent_HandleUpdatedCreatedBy; member.Flags |= EntityMemberFlags.NoDbUpdate; break; case AutoType.UpdatedBy: if (!CheckDataType(context, typeof(string))) { return; } entity.Events.New += EntityEvent_HandleUpdatedCreatedBy; entity.Events.Modified += EntityEvent_HandleUpdatedCreatedBy; break; case AutoType.CreatedById: entity.Events.New += EntityEvent_HandleUpdatedCreatedById; member.Flags |= EntityMemberFlags.NoDbUpdate; break; case AutoType.UpdatedById: entity.Events.New += EntityEvent_HandleUpdatedCreatedById; entity.Events.Modified += EntityEvent_HandleUpdatedCreatedById; break; case AutoType.RowVersion: member.Flags |= EntityMemberFlags.RowVersion | EntityMemberFlags.NoDbInsert | EntityMemberFlags.NoDbUpdate; member.Entity.Flags |= EntityFlags.HasRowVersion; member.ExplicitDbTypeSpec = "timestamp"; break; }//swith AutoValueType }
public static long GetSequenceNextValue(this IEntitySession session, SequenceDefinition sequence) { return(session.Select(() => sequence.NextValue())); }
public static long NextValue(this SequenceDefinition sequence) { Util.Throw("Function may not be called directly, only referenced in LINQ expressions."); return(0); // never happens }