Не совсем понятно, что для вас будет означать «мониторинг и ремонт», но:
Насколько вы контролируете базу данных? Кэш выполняет код для типа данных при преобразовании из глобального в ODBC с использованием метода LogicalToODBC класса данных. Если вы измените типы свойств с% String на свой собственный класс, AppappatelyNamedString, вы можете переопределить этот метод для автоматического усечения. Если это то, что вы хотите сделать. Можно изменить все типы свойств% String программно, используя класс% Library.CompiledClass.
Также возможно запустить код в Cache, чтобы найти записи со свойствами, которые имеют (несколько теоретическую) максимальную длину. Это, очевидно, потребует полного сканирования таблицы. Можно даже представить этот код как хранимую процедуру.
Опять же, я не знаю, что именно вы пытаетесь сделать, но это некоторые варианты. Они, вероятно, требуют углубления в сторону кэша, чем вы бы предпочли.
Что касается предотвращения неверных данных, то здесь нет общего ответа. Кэш позволяет программистам напрямую писать в глобальные переменные, минуя определения любого объекта или таблицы. Если это происходит, код, который делает это, должен быть исправлен напрямую.
Редактировать: вот код, который может работать при обнаружении неверных данных. Это может не сработать, если вы делаете что-то смешное, но это сработало для меня. Это некрасиво, потому что я не хотел разбивать его на методы или теги. Он предназначен для запуска из командной строки, поэтому, вероятно, его придется изменить для ваших целей.
{
S ClassQuery=##CLASS(%ResultSet).%New("%Dictionary.ClassDefinition:SubclassOf")
I 'ClassQuery.Execute("%Library.Persistent") b q
While ClassQuery.Next(.sc) {
If $$$ISERR(sc) b Quit
S ClassName=ClassQuery.Data("Name")
I $E(ClassName)="%" continue
S OneClassQuery=##CLASS(%ResultSet).%New(ClassName_":Extent")
I '$IsObject(OneClassQuery) continue //may not exist
try {
I 'OneClassQuery.Execute() D OneClassQuery.Close() continue
}
catch
{
D OneClassQuery.Close()
continue
}
S PropertyQuery=##CLASS(%ResultSet).%New("%Dictionary.PropertyDefinition:Summary")
K Properties
s sc=PropertyQuery.Execute(ClassName) I 'sc D PropertyQuery.Close() continue
While PropertyQuery.Next()
{
s PropertyName=$G(PropertyQuery.Data("Name"))
S PropertyDefinition=""
S PropertyDefinition=##CLASS(%Dictionary.PropertyDefinition).%OpenId(ClassName_"||"_PropertyName)
I '$IsObject(PropertyDefinition) continue
I PropertyDefinition.Private continue
I PropertyDefinition.SqlFieldName=""
{
S Properties(PropertyName)=PropertyName
}
else
{
I PropertyName'="" S Properties(PropertyDefinition.SqlFieldName)=PropertyName
}
}
D PropertyQuery.Close()
I '$D(Properties) continue
While OneClassQuery.Next(.sc2) {
B:'sc2
S ID=OneClassQuery.Data("ID")
Set OneRowQuery=##class(%ResultSet).%New("%DynamicQuery:SQL")
S sc=OneRowQuery.Prepare("Select * FROM "_ClassName_" WHERE ID=?") continue:'sc
S sc=OneRowQuery.Execute(ID) continue:'sc
I 'OneRowQuery.Next() D OneRowQuery.Close() continue
S PropertyName=""
F S PropertyName=$O(Properties(PropertyName)) Q:PropertyName="" d
. S PropertyValue=$G(OneRowQuery.Data(PropertyName))
. I PropertyValue'="" D
.. S PropertyIsValid=$ZOBJClassMETHOD(ClassName,Properties(PropertyName)_"IsValid",PropertyValue)
.. I 'PropertyIsValid W !,ClassName,":",ID,":",PropertyName," has invalid value of "_PropertyValue
.. //I PropertyIsValid W !,ClassName,":",ID,":",PropertyName," has VALID value of "_PropertyValue
D OneRowQuery.Close()
}
D OneClassQuery.Close()
}
D ClassQuery.Close()
}