示例#1
0
 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");
                }
            }
        }
示例#4
0
        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);
        }
示例#5
0
        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>");
        }
示例#6
0
		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");
				}
			}
		}
示例#8
0
		/// <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>");
		}
示例#9
0
			public ARLoaderEnumerator(Type arType, IEnumerable keys)
				: base(keys.GetEnumerator())
			{
				this.pkModel = ActiveRecordModel.GetModel(arType).PrimaryKey;
				this.arType = arType;
			}
示例#10
0
 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>");
        }
示例#15
0
        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;
                        }
                    }
                }
            }
        }