public async Task <bool> ValidateEntity(RunTimeMetadata metadata, RequestContext requestContext)
        {
            RowInfo   rowInfo   = requestContext.CurrentRowInfo;
            DbSetInfo dbSetInfo = rowInfo.GetDbSetInfo();
            IEnumerable <ValidationErrorInfo> errs1 = null;
            IEnumerable <ValidationErrorInfo> errs2 = null;
            LinkedList <string> mustBeChecked       = new LinkedList <string>();
            LinkedList <string> skipCheckList       = new LinkedList <string>();

            if (rowInfo.changeType == ChangeType.Added)
            {
                foreach (ParentChildNode pn in rowInfo.GetChangeState().ParentRows)
                {
                    foreach (FieldRel frel in pn.Association.fieldRels)
                    {
                        skipCheckList.AddLast(frel.childField);
                    }
                }
            }

            foreach (Field fieldInfo in dbSetInfo.fieldInfos)
            {
                _dataHelper.ForEachFieldInfo("", fieldInfo, (fullName, f) =>
                {
                    if (!f.GetIsIncludeInResult())
                    {
                        return;
                    }

                    if (f.fieldType == FieldType.Object || f.fieldType == FieldType.ServerCalculated)
                    {
                        return;
                    }

                    string value = _dataHelper.SerializeField(rowInfo.GetChangeState().Entity, fullName, f);

                    switch (rowInfo.changeType)
                    {
                    case ChangeType.Added:
                        {
                            bool isSkip = f.isAutoGenerated || skipCheckList.Any(n => n == fullName);
                            if (!isSkip)
                            {
                                _validationHelper.CheckValue(f, value);
                                mustBeChecked.AddLast(fullName);
                            }
                        }
                        break;

                    case ChangeType.Updated:
                        {
                            bool isChanged = isEntityValueChanged(rowInfo, fullName, f, out string newVal);
                            if (isChanged)
                            {
                                _validationHelper.CheckValue(f, newVal);
                                mustBeChecked.AddLast(fullName);
                            }
                        }
                        break;
                    }
                });
            }

            rowInfo.GetChangeState().ChangedFieldNames = mustBeChecked.ToArray();

            MethodInfoData methodData = metadata.GetOperationMethodInfo(dbSetInfo.dbSetName, MethodType.Validate);

            if (methodData != null)
            {
                object instance  = GetMethodOwner(methodData);
                object invokeRes = methodData.MethodInfo.Invoke(instance,
                                                                new[] { rowInfo.GetChangeState().Entity, rowInfo.GetChangeState().ChangedFieldNames });
                errs1 = (IEnumerable <ValidationErrorInfo>) await GetMethodResult(invokeRes);
            }

            if (errs1 == null)
            {
                errs1 = Enumerable.Empty <ValidationErrorInfo>();
            }

            IValidator validator = _validatorsContainer.GetValidator(rowInfo.GetDbSetInfo().GetEntityType());

            if (validator != null)
            {
                errs2 = await validator.ValidateModelAsync(rowInfo.GetChangeState().Entity,
                                                           rowInfo.GetChangeState().ChangedFieldNames);
            }

            if (errs2 == null)
            {
                errs2 = Enumerable.Empty <ValidationErrorInfo>();
            }

            errs1 = errs1.Concat(errs2);

            rowInfo.GetChangeState().ValidationErrors = errs1.ToArray();

            return(rowInfo.GetChangeState().ValidationErrors.Length == 0);
        }