Вы можете установить желаемый формат:
dataGridViewCellStyle.Format = "dd/MM/yyyy";
this.date.DefaultCellStyle = dataGridViewCellStyle;
// date being a System.Windows.Forms.DataGridViewTextBoxColumn
И снова процесс составления моих мыслей по вопросу дает ответ. В частности, последнее предложение, где я писал «по одной строке за раз». Я понял, что мне все равно, что это устройство чтения данных, пока я могу перечислять его строка за строкой. Это привело меня к следующему:
public IEnumerable<IDataRecord> GetSomeData(string filter)
{
string sql = "SELECT * FROM [SomeTable] WHERE SomeColumn= @Filter";
using (SqlConnection cn = new SqlConnection(GetConnectionString()))
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter;
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
}
Это будет работать еще лучше, когда мы перейдем на 3.5 и сможем начать использовать другие операторы linq для результатов, и мне это нравится, потому что это заставляет нас начать думать в терминах «конвейера» между каждый уровень для запросов, которые возвращают много результатов.
Обратной стороной является то, что читателям, имеющим более одного набора результатов, будет неудобно, но это очень редко.
Обновление
С тех пор, как я начал играя с этим шаблоном в 2009 году, я понял, что лучше всего, если я также сделаю его общим IEnumerable
и добавьте параметр Func
для преобразования состояния DataReader в бизнес-объекты в цикле. В противном случае могут возникнуть проблемы с отложенной итерацией, из-за которых вы каждый раз будете видеть последний объект в запросе.
В такие времена я считаю, что лямбды могут быть очень полезны. Учтите, что вместо уровня данных, предоставляющего нам данные, давайте дадим уровню данных наш метод обработки данных:
public void GetSomeData(string filter, Action<IDataReader> processor)
{
...
using (IDataReader reader = cmd.ExecuteReader())
{
processor(reader);
}
}
Тогда бизнес-уровень назовет его:
GetSomeData("my filter", (IDataReader reader) =>
{
while (reader.Read())
{
...
}
});
То, что вам нужно, это поддерживаемый шаблон, вам нужно будет использовать
cmd.ExecuteReader(CommandBehavior.CloseConnection);
и удалить оба с помощью ()
из вашего метода GetSomeData (). Вызывающая сторона должна обеспечивать безопасность при исключениях, чтобы гарантировать закрытие для считывателя.
Я никогда не был большим поклонником того, чтобы уровень данных возвращал общий объект данных, так как это в значительной степени растворяет весь смысл разделения кода на его собственный уровень (как вы можете отключить слоев данных, если интерфейс не определен?).
Я думаю, что лучше всего для всех подобных функций возвращать список настраиваемых объектов, которые вы создаете сами, а в своих данных позже вы вызываете свою процедуру / запрос в считыватель данных и итерации по нему, создавая список.
Это упростит работу в целом (несмотря на первоначальное время для создания настраиваемых классов), упростит обработку вашего соединения (поскольку вы не будете возврат любых связанных с ним объектов) и должен быть быстрее. Единственный недостаток - все будет загружено в память, как вы упомянули, но я бы не стал