public bool ActivateFor(IRow row)
        {
            if (Target is null)
            {
                return(false);
            }

            attr = Target.GetAttribute <LinkingSetRelationAttribute>();
            if (attr == null)
            {
                return(false);
            }

            if (!(row is IIdRow))
            {
                throw new ArgumentException(string.Format("Field '{0}' in row type '{1}' has a [LinkingSetRelation] attribute " +
                                                          "but it doesn't implement IIdRow!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            var listType = Target.ValueType;

            if (!listType.IsGenericType ||
                listType.GetGenericTypeDefinition() != typeof(List <>))
            {
                throw new ArgumentException(string.Format("Field '{0}' in row type '{1}' has a [LinkingSetRelation] attribute " +
                                                          "but its property type is not a generic List (e.g. List<int>)!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowType = attr.RowType;
            if (rowType.IsAbstract ||
                !typeof(IRow).IsAssignableFrom(rowType) ||
                rowType.IsInterface)
            {
                throw new ArgumentException(string.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type is not valid row class!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            if (!typeof(IIdRow).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(string.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type doesn't implement IIdRow!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            listFactory = () => (IList)Activator.CreateInstance(listType);
            rowFactory  = () => (IRow)Activator.CreateInstance(rowType);

            var detailRow = rowFactory();

            thisKeyField = detailRow.FindFieldByPropertyName(attr.ThisKey) ??
                           detailRow.FindField(attr.ThisKey);

            if (thisKeyField is null)
            {
                throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ThisKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            thisKeyCriteria = new Criteria(thisKeyField.PropertyName ?? thisKeyField.Name);

            itemKeyField = detailRow.FindFieldByPropertyName(attr.ItemKey) ??
                           detailRow.FindField(attr.ItemKey);

            if (itemKeyField is null)
            {
                throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ItemKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            if (!string.IsNullOrEmpty(attr.FilterField))
            {
                filterField = detailRow.FindFieldByPropertyName(attr.FilterField) ?? detailRow.FindField(attr.FilterField);
                if (filterField is null)
                {
                    throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                              "This field is specified for a linking set relation as FilterField in field '{2}' of row type '{3}'.",
                                                              attr.FilterField, detailRow.GetType().FullName,
                                                              Target.PropertyName ?? Target.Name, row.GetType().FullName));
                }

                filterCriteria = new Criteria(filterField.PropertyName ?? filterField.Name);
                filterValue    = filterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                if (filterValue == null)
                {
                    filterCriteria = filterCriteria.IsNull();
                    queryCriteria  = filterField.IsNull();
                }
                else
                {
                    filterCriteria = filterCriteria == new ValueCriteria(filterValue);
                    queryCriteria  = filterField == new ValueCriteria(filterValue);
                }
            }

            queryCriteria &= ServiceQueryHelper.GetNotDeletedCriteria(detailRow);

            return(true);
        }
        public bool ActivateFor(IRow row)
        {
            if (Target is null)
            {
                return(false);
            }

            attr = Target.GetAttribute <MasterDetailRelationAttribute>();
            if (attr == null)
            {
                return(false);
            }

            var rowListType = Target.ValueType;

            if (!rowListType.IsGenericType ||
                rowListType.GetGenericTypeDefinition() != typeof(List <>))
            {
                throw new ArgumentException(string.Format("Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                                                          "but its property type is not a generic List (e.g. List<IRow>)!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowType = rowListType.GetGenericArguments()[0];
            if (rowType.IsAbstract ||
                !typeof(IRow).IsAssignableFrom(rowType) ||
                rowType.IsInterface)
            {
                throw new ArgumentException(string.Format(
                                                "Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                                                "but its property type is not a generic list of rows (e.g. List<IRow>)!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowListFactory = () => (IList)Activator.CreateInstance(rowListType);
            rowFactory     = () => (IRow)Activator.CreateInstance(rowType);

            if (attr.MasterKeyField != null)
            {
                // Use field from AltIdField
                masterKeyField = row.FindFieldByPropertyName(attr.MasterKeyField) ??
                                 row.FindField(attr.MasterKeyField);

                if (masterKeyField is null)
                {
                    throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                              "This field is specified for a master detail relation in field '{2}'.",
                                                              attr.MasterKeyField, row.GetType().FullName,
                                                              Target.PropertyName ?? Target.Name));
                }
            }
            else
            {
                // Default behaviour: use id field
                masterKeyField = row.IdField;
            }

            var detailRow = rowFactory();

            foreignKeyField = detailRow.FindFieldByPropertyName(attr.ForeignKey) ??
                              detailRow.FindField(attr.ForeignKey);

            if (foreignKeyField is null)
            {
                throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a master detail relation in field '{2}' of row type '{3}'.",
                                                          attr.ForeignKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            foreignKeyCriteria = new Criteria(foreignKeyField.PropertyName ?? foreignKeyField.Name);

            if (!string.IsNullOrEmpty(attr.FilterField))
            {
                filterField = detailRow.FindFieldByPropertyName(attr.FilterField) ?? detailRow.FindField(attr.FilterField);
                if (filterField is null)
                {
                    throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                              "This field is specified for a master detail relation as FilterField in field '{2}' of row type '{3}'.",
                                                              attr.FilterField, detailRow.GetType().FullName,
                                                              Target.PropertyName ?? Target.Name, row.GetType().FullName));
                }

                filterCriteria = new Criteria(filterField.PropertyName ?? filterField.Name);
                filterValue    = filterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                if (filterValue == null)
                {
                    filterCriteria = filterCriteria.IsNull();
                    queryCriteria  = filterField.IsNull();
                }
                else
                {
                    filterCriteria = filterCriteria == new ValueCriteria(filterValue);
                    queryCriteria  = filterField == new ValueCriteria(filterValue);
                }
            }

            queryCriteria &= ServiceQueryHelper.GetNotDeletedCriteria(detailRow);

            includeColumns = new HashSet <string>();

            if (!string.IsNullOrEmpty(attr.IncludeColumns))
            {
                foreach (var s in attr.IncludeColumns.Split(','))
                {
                    var col = s.TrimToNull();
                    if (col != null)
                    {
                        includeColumns.Add(col);
                    }
                }
            }

            return(true);
        }