Как установить максимальное количество строк в базе данных sql для каждого значения атрибута [duplicate]

К несчастью для меня, у меня был случай, когда класс, который должен быть сериализован, имел свойства с интерфейсами как свойствами, поэтому мне нужно было рекурсивно обрабатывать каждое свойство. Кроме того, некоторые свойства интерфейса были отмечены как [XmlIgnore], поэтому я хотел пропустить их. Я взял идеи, которые я нашел в этой теме, и добавил некоторые вещи к ней, чтобы сделать ее рекурсивной. Здесь показан только код десериализации:

  void main () {var serializer = GetDataContractSerializer & lt; MyObjectWithCascadingInterfaces & gt; ();  используя (FileStream stream = новый FileStream (xmlPath, FileMode.Open)) {XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader (поток, новый XmlDictionaryReaderQuotas ());  var obj = (MyObjectWithCascadingInterfaces) serializer.ReadObject (reader);  // ваш код здесь}} DataContractSerializer GetDataContractSerializer & lt; T & gt; (), где T: new () {Тип [] types = GetTypesForInterfaces & lt; T & gt; ();  // Отфильтровать дубликаты Тип [] result = types.ToList (). Distinct (). ToList (). ToArray ();  var obj = new T ();  вернуть новый DataContractSerializer (obj.GetType (), типы);  } Тип [] GetTypesForInterfaces & lt; T & gt; (), где T: new () {return GetTypesForInterfaces (typeof (T));  } Тип [] GetTypesForInterfaces (Тип T) {Тип [] result = new Тип [0];  var obj = Activator.CreateInstance (T);  // получить тип для всех свойств интерфейса, которые не помечены как «XmlIgnore» Type [] types = T.GetProperties () .Where (p = & gt; p.PropertyType.IsInterface & amp;! p.GetCustomAttributes (typeof (  System.Xml.Serialization.XmlIgnoreAttribute), false) .Any ()). Выбрать (p = & gt; p.GetValue (obj, null) .GetType ()) .ToArray ();  result = result.ToList (). Concat (types.ToList ()). ToArray ();  // делаем то же самое для каждого из типов, определенных foreach (тип t в типах) {Type [] embeddedTypes = GetTypesForInterfaces (t);  result = result.ToList (). Concat (embeddedTypes.ToList ()). ToArray ();  } return result;  }  
18
задан jeje 16 November 2009 в 17:58
поделиться

3 ответа

Квасной прав; триггер был бы лучшим способом для этого.

Вот код:

  СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ ensce_photo_count () RETURNS trigger AS $$ DECLARE max_photo_count INTEGER: = 10  ;  photo_count INTEGER: = 0;  must_check BOOLEAN: = false;  BEGIN IF TG_OP = 'INSERT' THEN must_check: = true;  END IF;  IF TG_OP = 'UPDATE' THEN IF (NEW.owner! = OLD.owner) THEN must_check: = true;  END IF;  END IF;  IF must_check THEN - предотвращать одновременные вставки из нескольких транзакций LOCK TABLE photos В ЭКСКЛЮЗИВНОМ РЕЖИМЕ;  SELECT INTO photo_count COUNT (*) FROM photos WHERE owner = NEW.owner;  IF photo_count & gt; = max_photo_count ТОГДА ИСКЛЮЧЕНИЕ ПОДЪЕМА «Невозможно вставить больше, чем% фотографий для каждого пользователя.», Max_photo_count;  END IF;  END IF;  ВОЗВРАТ НОВЫЙ;  КОНЕЦ;  $$ LANGUAGE plpgsql;  CREATE TRIGGER enforce_photo_count ПЕРЕД ВСТАВКОЙ ИЛИ ОБНОВЛЕНИЕМ НА ФОТОГРАФИЯХ ДЛЯ КАЖДОЙ ПРОЦЕДУРЫ ROW EXECUTE enforce_photo_count ();   

Я включил блокировку таблицы, чтобы избежать ситуаций, когда два одновременных tansactions будут считать фотографии для пользователя, см., что текущий счетчик равен 1 ниже предела, а затем оба вставки, которые могли бы вызвать вы должны перейти 1 за пределы. Если это вас не волнует, было бы лучше удалить блокировку, поскольку она может стать узким местом со множеством вставок / обновлений.

20
ответ дан Aleksander Kmetec 15 August 2018 в 23:39
поделиться
  • 1
    Еще одна вещь: к сожалению, все операторы IF в начале триггера не могут быть объединены в один «IF TG_OP =« INSERT »OR (TG_OP =« ОБНОВЛЕНИЕ »И NEW.owner! = OLD.owner) THEN ... & Quot; потому что PLPGSQL не поддерживает короткое замыкание. – Aleksander Kmetec 16 November 2009 в 18:51

Вы не можете записать такое ограничение в объявлении таблицы.

Существуют некоторые способы обхода:

  • Создайте триггер, который будет проверять количество фотографий для каждого пользователя [ ! d4]
  • Создайте столбец photo_order , который сохранит порядок фотографий, сделайте (user_id, photo_order) UNIQUE и добавьте CHECK (photo_order BETWEEN 1 И 10)
7
ответ дан Quassnoi 15 August 2018 в 23:39
поделиться
  • 1
    Разве вы не должны были бы принуждать к уникальности при заказе фотографии? Как это сделать? – ahnbizcad 8 November 2014 в 19:21

Другим подходом было бы добавить столбец «photo_count» в таблицу users, обновить его с помощью триггеров, чтобы он отражал реальность, и добавить его, чтобы обеспечить максимальное количество фотографий.

Боковое преимущество от это то, что в любой момент мы знаем (без учета), сколько у пользователя фотографий.

С другой стороны, подход Quassnoi также довольно крут, поскольку он дает вам возможность переупорядочивать фотографии в случае пользователь хотел бы этого.

2
ответ дан user 15 August 2018 в 23:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: