Использование статического набора данных в качестве источника данных
В моем приложении у меня есть DataSet, который содержит таблицы, которые используются в разных формах, по всему моему приложению. Чтобы поддерживать параллелизм между формами и не получать данные из базы данных каждый раз, когда пользователь открывает новую форму, я храню свой DataSet как статическое поле в классе программы, например:
static class Program
{
public static CustomDataSet StockDataSet { get; private set; }
[STAThread]
static void Main()
{
StockDataSet = new Database.CustomDataSet();
StockDataSet.InitRelations();
StockDataSet.EnforceConstraints = false;
StockDataSet.Categories.Fill();
StockDataSet.Suppliers.Fill();
StockDataSet.StockItems.Fill();
StockDataSet.EnforceConstraints = true;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow());
}
Это позволяет довольно просто использовать DataSet программно. Работа во время разработки, однако, вызывает много разочарований. Для экзамена; У меня есть форма с DataGridView, связанной с BindingSource. Если я хочу иметь возможность работать со столбцами DataGridView во время разработки, у меня должен быть объект моего пользовательского набора данных, доступный для BindingSource в InitializeComponent.
Все обходные пути для этого, я могу придумать, довольно уродливые хаки. Например, использование фиктивного объекта в Designer.cs для поддержания времени разработки, а затем назначение статического объекта полю, содержащему фиктивный объект. И после этого сбросьте все привязки в конструкторе. Это должно считаться очень плохой практикой, верно?
Поэтому мой вопрос заключается в следующем: нет ли более элегантного или хотя бы практического подхода к этому? Или есть какие-либо рекомендации по работе с наборами данных в нескольких формах?
редактировать
Запас относится к хранению как в инвентаре. Не выполняется никакой тяжелой обработки данных, которые хранятся в базе данных MySql на локальном сервере.
3 ответа
Отображение одного источника данных во время выполнения, а другого в DesignTime совсем не страшно. Я думаю, что то, с чем вы боретесь, довольно распространено, когда используются DataTables, DataSets, DataGridViews и дизайнер. Это отличный инструмент, если вы работаете с очень простыми формами Master/Detail и не хотите выходить за рамки стандартного поведения.
В описанном вами сценарии вы хотите изменить обычное использование этих элементов, чтобы вы могли предварительно загружать данные при запуске приложения. Как вы узнали, это вызывает некоторые проблемы, с которыми вам теперь придется справиться самостоятельно. Частью решения этой проблемы является сброс DataSource к новому значению во время выполнения. Это совсем не безумие или плохая практика.
Однако, когда вы начинаете говорить о подделках и кешировании из-за проблем с производительностью, я задаюсь вопросом, действительно ли вам нужна база данных вообще. Похоже, вы хотите разработать модель (используя объекты C#), которую вы можете привязывать, обновлять и сериализовать по мере необходимости. Хотя я не уверен, что это верно для вашего дизайна, если бы это был мой дизайн (с моим ограниченным пониманием вашей проблемы), это было бы то, чем я бы занимался. База данных не будет большой частью моего проекта на данный момент, если вообще. Я бы построил объекты C#, которые представляют мои таблицы, класс модели для управления этими элементами и фабрику для создания экземпляра модели и управления ее временем жизни.
Если бы в какой-то момент мне пришлось сериализовать / взаимодействовать с / с базой данных, я бы встроил это в модель.
Более важный вопрос для меня в отношении элегантности: как бы я все это проверил? Если я привязываюсь во время разработки и полагаюсь на статическую загрузку во время выполнения, тогда моя конструкция не позволяет мне выполнять какие-либо модульные или интеграционные тесты на основе классов. Если бы я разделил содержимое базы данных на модель, то я бы разделил заботу об управлении данными на класс, в который я мог бы вставить интерфейс, что давало бы мне что-то подделать или посмеяться и заглушить.
Попробуйте использовать шаблон дизайна Singleton.
public sealed class DB
{
private static readonly DB instance = new DB( );
public static DB Instance { get { return instance; } }
static DB( ) { }
private DB( )
{
StaticData = new DataSet( );
}
private static DataSet StaticData;
public DataTable GetCategoryTable( )
{
// check if the table has been created
if( StaticData.Tables["Category"] == null )
{
// build table (or retrieve from database)
DataTable table = new DataTable( );
table.TableName = "Category";
table.Columns.Add( "ID", typeof( int ) );
table.Columns.Add( "Name", typeof( string ) );
table.Columns.Add( "Description", typeof( string ) );
table.Rows.Add( 1, "Beverages", "Soft drinks, coffees, teas, beers, and ales" );
table.Rows.Add( 2, "Condiments", "Sweet and savory sauces, relishes, spreads, and seasonings" );
table.Rows.Add( 3, "Produce", "Dried fruit and bean curd" );
table.Rows.Add( 4, "Seafood", "Seaweed and fish" );
table.Rows.Add( 5, "Meat/Poultry", "Prepared meats" );
StaticData.Tables.Add(table.Copy());
}
return StaticData.Tables["Category"];
}
public DataTable GetStatusTable( )
{
// check if the table has been created
if( StaticData.Tables["Status"] == null )
{
// build table (or retrieve from database)
DataTable table = new DataTable( );
table.TableName = "Status";
table.Columns.Add( "ID", typeof( int ) );
table.Columns.Add( "Name", typeof( string ) );
table.Columns.Add( "Description", typeof( string ) );
table.Rows.Add( 1, "Active", "Active" );
table.Rows.Add( 2, "Retired", "Retired" );
StaticData.Tables.Add( table.Copy( ) );
}
return StaticData.Tables["Status"];
}
}
Используйте это так:
private void Form1_Load( object sender, EventArgs e )
{
DB db = DB.Instance;
dataGridView1.DataSource = db.GetCategoryTable( );
dataGridView2.DataSource = db.GetCategoryTable( );
dataGridView3.DataSource = db.GetStatusTable( );
}
Я хотел бы пойти с идеей использования фиктивного объекта в Designer.cs, но прокомментировать соответствующий раздел, используя условную компиляцию (т.е. #if DEBUG)