public override void VisitPrimaryKey(PrimaryKeyModel model) { if (model.Property.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), false).Length > 0) { DoNaturalKey(model); } else { DoSurrogateKey(model); } }
/// <summary> /// Perform the check that the property value is unqiue in the table /// </summary> /// <param name="instance"></param> /// <param name="fieldValue"></param> /// <returns><c>true</c> if the field is OK</returns> public override bool IsValid(object instance, object fieldValue) { Type instanceType = instance.GetType(); ActiveRecordModel model = ActiveRecordBase.GetModel(instance.GetType()); while(model != null) { if (model.PrimaryKey != null) { pkModel = model.PrimaryKey; } model = model.Parent; } if (pkModel == null) { throw new ValidationFailure("We couldn't find the primary key for " + instanceType.FullName + " so we can't ensure the uniqueness of any field. Validatior failed"); } IsUniqueValidator.fieldValue = fieldValue; SessionScope scope = null; FlushMode? originalMode = null; if (SessionScope.Current == null /*|| SessionScope.Current.ScopeType != SessionScopeType.Transactional*/) { scope = new SessionScope(); } else { originalMode = ActiveRecordBase.holder.CreateSession(instanceType).FlushMode; ActiveRecordBase.holder.CreateSession(instanceType).FlushMode = FlushMode.Never; } try { return (bool) ActiveRecordMediator.Execute(instanceType, CheckUniqueness, instance); } finally { if (scope != null) { scope.Dispose(); } if (originalMode != null) { ActiveRecordBase.holder.CreateSession(instanceType).FlushMode = originalMode ?? FlushMode.Commit; } } }
/// <summary> /// Visits the primary key. /// </summary> /// <remarks> /// Infer column name and the reverse property if using [OneToOne] /// </remarks> /// <param name="model">The model.</param> public override void VisitPrimaryKey(PrimaryKeyModel model) { if (model.PrimaryKeyAtt.Column == null) { model.PrimaryKeyAtt.Column = model.Property.Name; } // Append column prefix model.PrimaryKeyAtt.Column = columnPrefix + model.PrimaryKeyAtt.Column; if (model.PrimaryKeyAtt.Generator == PrimaryKeyType.Foreign) { // Let's see if we are an OneToOne if (currentModel.OneToOnes.Count != 0) { // Yes, set the one to one as param OneToOneModel oneToOne = currentModel.OneToOnes[0]; String param = "property=" + oneToOne.Property.Name; if (model.PrimaryKeyAtt.Params == null) { model.PrimaryKeyAtt.Params = param; } else { model.PrimaryKeyAtt.Params += "," + param; } } } else if (model.PrimaryKeyAtt.Generator == PrimaryKeyType.Custom) { if (model.PrimaryKeyAtt.CustomGenerator == null) { throw new ActiveRecordException(String.Format( "A type defined that its primary key would use a custom generator, " + "but apparently forgot to define the custom generator using PrimaryKeyAttribute.CustomGenerator property. " + "Check type {0}", currentModel.Type.FullName)); } if (!typeof(IIdentifierGenerator).IsAssignableFrom(model.PrimaryKeyAtt.CustomGenerator)) { throw new ActiveRecordException( "The custom generator associated with the PK for the type " + currentModel.Type.FullName + "does not implement interface NHibernate.Id.IIdentifierGenerator"); } } }
public override String ToString() { Framework.Internal.ActiveRecordModel model = GetModel(GetType()); if (model == null || model.Ids.Count != 1) { return(base.ToString()); } Framework.Internal.PrimaryKeyModel pkModel = (Framework.Internal.PrimaryKeyModel)model.Ids[0]; object pkVal = pkModel.Property.GetValue(this, null); return(base.ToString() + "#" + pkVal); }
private void DoNaturalKey(PrimaryKeyModel model) { CompositeKeyAttribute att = model.Property.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), false)[0] as CompositeKeyAttribute; string unsavedVal = att.UnsavedValue; if (unsavedVal == null) { unsavedVal = "none"; } AppendF("<composite-id {0} {1} {2} {3}>", MakeAtt("name", model.Property.Name), MakeClassAtt(model.Property.PropertyType), WriteIfNonNull("unsaved-value", unsavedVal), MakeAtt("access", att.AccessString)); Ident(); PropertyInfo[] keyProps = model.Property.PropertyType.GetProperties(); foreach (PropertyInfo keyProp in keyProps) { KeyPropertyAttribute keyPropAttr = keyProp.GetCustomAttributes(typeof(KeyPropertyAttribute), false)[0] as KeyPropertyAttribute; if (keyPropAttr.Column == null) { keyPropAttr.Column = keyProp.Name; } AppendF("<key-property {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} />", MakeAtt("name", keyProp.Name), MakeAtt("access", keyPropAttr.AccessString), MakeAtt("column", keyPropAttr.Column), MakeTypeAtt(keyProp.PropertyType, keyPropAttr.ColumnType), WriteIfNotZero("length", keyPropAttr.Length), WriteIfNonNull("unsaved-value", keyPropAttr.UnsavedValue), WriteIfTrue("not-null", keyPropAttr.NotNull), WriteIfTrue("unique", keyPropAttr.Unique), WriteIfFalse("insert", keyPropAttr.Insert), WriteIfFalse("update", keyPropAttr.Update), WriteIfNonNull("formula", keyPropAttr.Formula)); } Dedent(); AppendF("</composite-id>"); }
private object ObtainPrimaryKeyValue(ActiveRecordModel model, CompositeNode node, String prefix, out PrimaryKeyModel pkModel) { pkModel = ObtainPrimaryKey(model); var pkPropName = pkModel.Property.Name; var idNode = node.GetChildNode(pkPropName); if (idNode == null) return null; if (idNode != null && idNode.NodeType != NodeType.Leaf) { throw new BindingException("Expecting leaf node to contain id for ActiveRecord class. " + "Prefix: {0} PK Property Name: {1}", prefix, pkPropName); } var lNode = (LeafNode) idNode; if (lNode == null) { throw new BindingException("ARDataBinder autoload failed as element {0} " + "doesn't have a primary key {1} value", prefix, pkPropName); } bool conversionSuc; return Converter.Convert(pkModel.Property.PropertyType, lNode.ValueType, lNode.Value, out conversionSuc); }
/// <summary> /// Visits the primary key. /// </summary> /// <remarks> /// Infer column name and the reverse property if using [OneToOne] /// </remarks> /// <param name="model">The model.</param> public override void VisitPrimaryKey(PrimaryKeyModel model) { if (model.PrimaryKeyAtt.Column == null) { model.PrimaryKeyAtt.Column = model.Property.Name; } // Append column prefix model.PrimaryKeyAtt.Column = columnPrefix + model.PrimaryKeyAtt.Column; if (model.PrimaryKeyAtt.Generator == PrimaryKeyType.Foreign) { // Let's see if we are an OneToOne if (currentModel.OneToOnes.Count != 0) { // Yes, set the one to one as param OneToOneModel oneToOne = currentModel.OneToOnes[0]; String param = "property=" + oneToOne.Property.Name; if (model.PrimaryKeyAtt.Params == null) { model.PrimaryKeyAtt.Params = param; } else { model.PrimaryKeyAtt.Params += "," + param; } } } else if (model.PrimaryKeyAtt.Generator == PrimaryKeyType.Custom) { if (model.PrimaryKeyAtt.CustomGenerator == null) { throw new ActiveRecordException(String.Format( "A type defined that its primary key would use a custom generator, " + "but apparently forgot to define the custom generator using PrimaryKeyAttribute.CustomGenerator property. " + "Check type {0}", currentModel.Type.FullName)); } if (!typeof (IIdentifierGenerator).IsAssignableFrom(model.PrimaryKeyAtt.CustomGenerator)) { throw new ActiveRecordException( "The custom generator associated with the PK for the type " + currentModel.Type.FullName + "does not implement interface NHibernate.Id.IIdentifierGenerator"); } } }
/// <summary> /// Visits the primary key. /// </summary> /// <param name="model">The model.</param> public override void VisitPrimaryKey(PrimaryKeyModel model) { String unsavedVal = model.PrimaryKeyAtt.UnsavedValue; if (unsavedVal == null) { if (model.Property.PropertyType.IsPrimitive && model.Property.PropertyType != typeof(String)) { unsavedVal = "0"; } else if (model.Property.PropertyType == typeof(Guid)) { unsavedVal = Guid.Empty.ToString(); } } AppendF("<id{0}{1}{2}{3}{4}{5}>", MakeAtt("name", model.Property.Name), MakeAtt("access", model.PrimaryKeyAtt.AccessString), MakeAtt("column", model.PrimaryKeyAtt.Column), MakeTypeAtt(model.Property.PropertyType, model.PrimaryKeyAtt.ColumnType), WriteIfNotZero("length", model.PrimaryKeyAtt.Length), WriteIfNonNull("unsaved-value", unsavedVal)); Ident(); String className = null; switch(model.PrimaryKeyAtt.Generator) { case PrimaryKeyType.Identity: case PrimaryKeyType.Sequence: case PrimaryKeyType.HiLo: case PrimaryKeyType.SeqHiLo: case PrimaryKeyType.Guid: case PrimaryKeyType.Native: case PrimaryKeyType.Assigned: case PrimaryKeyType.Foreign: case PrimaryKeyType.Increment: className = model.PrimaryKeyAtt.Generator.ToString().ToLower(CultureInfo.InvariantCulture); break; case PrimaryKeyType.GuidComb: className = "guid.comb"; break; case PrimaryKeyType.UuidHex: className = "uuid.hex"; break; case PrimaryKeyType.UuidString: className = "uuid.string"; break; case PrimaryKeyType.Counter: className = "vm"; break; case PrimaryKeyType.Custom: className = MakeTypeName(model.PrimaryKeyAtt.CustomGenerator); break; } AppendF("<generator{0}>", MakeAtt("class", className)); if (model.PrimaryKeyAtt.SequenceName != null) { Ident(); AppendF("<param name=\"sequence\">{0}</param>", model.PrimaryKeyAtt.SequenceName); Dedent(); } if (model.PrimaryKeyAtt.Params != null) { Ident(); String[] paras = model.PrimaryKeyAtt.Params.Split(','); foreach(String param in paras) { int eqIndex = param.IndexOf("="); //need to handle parameters that may contains =, so we will take into account only the first one string paramName = param.Substring(0, eqIndex); string paramValue = param.Substring(eqIndex+1); AppendF("<param name=\"{0}\">{1}</param>", paramName, paramValue); } Dedent(); } AppendF("</generator>"); Dedent(); Append("</id>"); }
public ARLoaderEnumerator(Type arType, IEnumerable keys) : base(keys.GetEnumerator()) { this.pkModel = ActiveRecordModel.GetModel(arType).PrimaryKey; this.arType = arType; }
public virtual void VisitPrimaryKey(PrimaryKeyModel model) { }
/// <summary> /// Visits the primary key. /// </summary> /// <param name="model">The model.</param> public virtual void VisitPrimaryKey(PrimaryKeyModel model) { }
private static string GuessGeneratorClassName(PrimaryKeyModel model) { if (model.Property.PropertyType == typeof(Guid)) return "guid.comb"; if (model.Property.PropertyType == typeof(string)) return "assigned"; // NOTE: perhaps this could be extended to some other return "native"; }
private static string GetGeneratorClassName(PrimaryKeyModel model) { if (model.PrimaryKeyAtt.TypeSpecified == false) { return GuessGeneratorClassName(model); } String className = null; switch (model.PrimaryKeyAtt.Generator) { case PrimaryKeyType.Identity: case PrimaryKeyType.Sequence: case PrimaryKeyType.HiLo: case PrimaryKeyType.SeqHiLo: case PrimaryKeyType.Guid: case PrimaryKeyType.Native: case PrimaryKeyType.Assigned: case PrimaryKeyType.Foreign: case PrimaryKeyType.Increment: className = model.PrimaryKeyAtt.Generator.ToString().ToLower(CultureInfo.InvariantCulture); break; case PrimaryKeyType.GuidComb: className = "guid.comb"; break; case PrimaryKeyType.UuidHex: className = "uuid.hex"; break; case PrimaryKeyType.UuidString: className = "uuid.string"; break; case PrimaryKeyType.Counter: className = "vm"; break; case PrimaryKeyType.Custom: className = MakeTypeName(model.PrimaryKeyAtt.CustomGenerator); break; } return className; }
/// <summary> /// Visits the primary key. /// </summary> /// <param name="model">The model.</param> public override void VisitPrimaryKey(PrimaryKeyModel model) { String unsavedVal = model.PrimaryKeyAtt.UnsavedValue; if (unsavedVal == null) { if (model.Property.PropertyType.IsPrimitive && model.Property.PropertyType != typeof(String)) { unsavedVal = "0"; } else if (model.Property.PropertyType == typeof(Guid)) { unsavedVal = Guid.Empty.ToString(); } } AppendStartTag("id", MakeAtt("name", model.Property.Name), MakeAtt("access", model.PrimaryKeyAtt.AccessString), MakeAtt("column", model.PrimaryKeyAtt.Column), MakeTypeAtt(model.Property.PropertyType, model.PrimaryKeyAtt.ColumnType), WriteIfNotZero("length", model.PrimaryKeyAtt.Length), WriteIfNonNull("unsaved-value", unsavedVal)); Ident(); string className = GetGeneratorClassName(model); AppendStartTag("generator", MakeAtt("class", className)); if (model.PrimaryKeyAtt.SequenceName != null) { Ident(); AppendF("<param name=\"sequence\">{0}</param>", model.PrimaryKeyAtt.SequenceName); Dedent(); } if (model.PrimaryKeyAtt.Params != null) { Ident(); String[] paras = model.PrimaryKeyAtt.Params.Split(','); foreach(String param in paras) { int eqIndex = param.IndexOf("="); //need to handle parameters that may contains =, so we will take into account only the first one string paramName = param.Substring(0, eqIndex); string paramValue = param.Substring(eqIndex+1); AppendF("<param name=\"{0}\">{1}</param>", paramName, paramValue); } Dedent(); } AppendF("</generator>"); Dedent(); Append("</id>"); }
private void DoSurrogateKey(PrimaryKeyModel model) { String unsavedVal = model.PrimaryKeyAtt.UnsavedValue; if (unsavedVal == null) { if (model.Property.PropertyType.IsPrimitive && model.Property.PropertyType != typeof(String)) { unsavedVal = "0"; } else if (model.Property.PropertyType != typeof(Guid)) { // Nasty guess, but for 99.98% of situations it will be OK unsavedVal = ""; } } AppendF("<id {0} {1} {2} {3} {4} {5}>", MakeAtt("name", model.Property.Name), MakeAtt("access", model.PrimaryKeyAtt.AccessString), MakeAtt("column", model.PrimaryKeyAtt.Column), MakeTypeAtt(model.Property.PropertyType, model.PrimaryKeyAtt.ColumnType), WriteIfNotZero("length", model.PrimaryKeyAtt.Length), WriteIfNonNull("unsaved-value", unsavedVal)); Ident(); if (model.PrimaryKeyAtt.Generator != PrimaryKeyType.None) { String className = null; switch (model.PrimaryKeyAtt.Generator) { case PrimaryKeyType.Identity: case PrimaryKeyType.Sequence: case PrimaryKeyType.HiLo: case PrimaryKeyType.SeqHiLo: case PrimaryKeyType.Guid: case PrimaryKeyType.Native: case PrimaryKeyType.Assigned: case PrimaryKeyType.Foreign: className = model.PrimaryKeyAtt.Generator.ToString().ToLower(); break; case PrimaryKeyType.GuidComb: className = "guid.comb"; break; case PrimaryKeyType.UuidHex: className = "uuid.hex"; break; case PrimaryKeyType.UuidString: className = "uuid.string"; break; } AppendF("<generator {0}>", MakeAtt("class", className)); if (model.PrimaryKeyAtt.SequenceName != null) { Ident(); AppendF("<param name=\"sequence\">{0}</param>", model.PrimaryKeyAtt.SequenceName); Dedent(); } if (model.PrimaryKeyAtt.Params != null) { Ident(); String[] paras = model.PrimaryKeyAtt.Params.Split(','); foreach (String param in paras) { String[] pair = param.Split('='); AppendF("<param name=\"{0}\">{1}</param>", pair[0], pair[1]); } Dedent(); } AppendF("</generator>"); } Dedent(); Append("</id>"); }
public override void VisitPrimaryKey(PrimaryKeyModel model) { // check for composite key first if (model.Property.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), false).Length > 0) { MethodInfo eq = model.Property.PropertyType.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); MethodInfo hc = model.Property.PropertyType.GetMethod("GetHashCode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); if (eq == null || hc == null) { throw new ActiveRecordException(string.Format("To use type '{0}' as a composite id, you must implement Equals and GetHashCode.", model.Property.PropertyType.Name)); } if (model.Property.PropertyType.IsSerializable == false) { throw new ActiveRecordException(string.Format("To use type '{0}' as a composite id it must be Serializable.", model.Property.PropertyType.Name)); } int keyPropAttrCount = 0; PropertyInfo[] compositeKeyProps = model.Property.PropertyType.GetProperties(); foreach (PropertyInfo keyProp in compositeKeyProps) { if (keyProp.GetCustomAttributes(typeof(KeyPropertyAttribute), false).Length > 0) { keyPropAttrCount++; } } if (keyPropAttrCount < 2) { throw new ActiveRecordException(string.Format("To use type '{0}' as a composite id it must have two or more properties marked with the [KeyProperty] attribute.", model.Property.PropertyType.Name)); } } else { if (model.PrimaryKeyAtt.Column == null) { model.PrimaryKeyAtt.Column = model.Property.Name; } if (model.PrimaryKeyAtt.Generator == PrimaryKeyType.Foreign) { // Just a thought, let's see if we are a OneToOne if (currentModel.OneToOnes.Count != 0) { // Yes, set the one to one as param OneToOneModel oneToOne = (OneToOneModel)currentModel.OneToOnes[0]; String param = "property=" + oneToOne.Property.Name; if (model.PrimaryKeyAtt.Params == null) { model.PrimaryKeyAtt.Params = param; } else { model.PrimaryKeyAtt.Params += "," + param; } } } } }