Отладка и загрузка свойств
У меня есть объект, который представляет запись таблицы в моей базе данных, например, "Проект".
Мой класс User имеет различные свойства, которые являются записями других таблиц, например, "Клиент" или "Бухгалтерия". Они также имеют свойства для связанных таблиц.
Каждое из этих свойств возвращает локальное значение (уже загружено), если оно не равно нулю, и нет загруженной информации, оно генерирует запрос на получение этого значения из базы данных.
Моя проблема заключается в следующем: когда я устанавливаю точку останова и проверяю объект в окне отладки, он автоматически загружает все значения свойств и, следовательно, запрашивает базу данных.
При таком сценарии у меня не может быть точного и статичного снимка моего объекта в данный момент.
Есть ли способ, в коде, не проходить через эту часть кода, если в окне отладки? Например, что-то вроде этого:
public MyBaseObject GetProperty<T>(string columnName_, string alias_ = null) where T : MyBaseObject, new()
{
var ret = GetExtract<T>(columnName_, alias_);
// if the data are loaded
if (ret.Id != null)
return ret;
// Fake boolean I would like
if(InDebugWindowAfterAbreakPointForInstance)
return ret;
else
ret = LoadFromDatabase<T>(columnName_, alias_)
return ret;
}
Я нашел различные атрибуты с отладчиком, как DebuggerStepperBoundaryAttribute
, но ничего, что могло бы сделать что-то подобное.
1 ответ
В подобных ситуациях я знаю только один способ: DebuggerTypeProxy
тогда для каждого из ваших типов в этом прокси он имеет прямой доступ к полю поддержки, а не через свойство, которое вызывает поиск в базе данных.
Вот простой пример программы.
public class Program
{
public static void Main(string[] args)
{
var client = new Client();
Debugger.Break();
Debugger.Break();
}
}
[DebuggerTypeProxy(typeof(ClientDebugView))]
public class Client : MyBaseObject
{
private string _firstName;
private string _lastName;
public string FirstName
{
get
{
if (_firstName == null)
_firstName = GetProperty<string>("FirstName");
return _firstName;
}
set
{
if (Equals(_firstName, value))
return;
_firstName = value;
UpdateDatabase(_firstName, "FirstName");
}
}
public string LastName
{
get
{
if (_lastName == null)
_lastName = GetProperty<string>("LastName");
return _lastName;
}
set
{
if (Equals(_lastName, value))
return;
_lastName = value;
UpdateDatabase(_lastName, "LastName");
}
}
internal class ClientDebugView : MyBaseObjectDebugView
{
private readonly Client _client;
public ClientDebugView(Client client)
: base(client)
{
_client = client;
}
public string FirstName
{
get { return _client._firstName; }
}
public string LastName
{
get { return _client._lastName; }
}
}
}
[DebuggerTypeProxy(typeof(MyBaseObjectDebugView))]
public class MyBaseObject
{
private Guid? _id;
public Guid? Id
{
get
{
if (_id == null)
_id = GetProperty<Guid?>("Id");
return _id;
}
set
{
if (Equals(_id, value))
return;
_id = value;
UpdateDatabase(_id, "Id");
}
}
//Fake loading data from a database.
protected T GetProperty<T>(string columnName)
{
object ret = null;
switch (columnName)
{
case "Id":
ret = Guid.NewGuid();
break;
case "LastName":
ret = "Smith";
break;
case "FirstName":
ret = "John";
break;
default:
ret = null;
break;
}
return (T)ret;
}
protected void UpdateDatabase<T>(T id, string s)
{
throw new NotImplementedException();
}
internal class MyBaseObjectDebugView
{
private readonly MyBaseObject _baseObject;
public MyBaseObjectDebugView(MyBaseObject baseObject)
{
_baseObject = baseObject;
}
public Guid? Id
{
get { return _baseObject._id; }
}
}
}
Если вы просматриваете client
объект в отладчике вы увидите, что он оставляет поля поддержки null
между двумя точками останова, если вы не откроете "Raw View" в первой точке останова.