Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: VB

Программирование VB

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: отображение данных.
 
 автор: Едрёныч   (23.03.2010 в 14:26)   личное сообщение
 
 

Делаю код по книге Д. Сеппы:

Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient
Public Class Form2


Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strConn, strSQL1 As String
strConn = "Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated Security=True;Asynchronous Processing=True;"
strSQL1 = "Select OrderID, CustomerID, OrderDate, ShippedDate, ShipCity" & _
" From Orders Where ShipCountry='Canada'"
Dim cn As New SqlConnection(strConn)
cn.Open()
Dim cmd As SqlCommand = cn.CreateCommand()
cmd.CommandText = strSQL1
Dim rdr As SqlDataReader = cmd.ExecuteReader()


End Sub

Вопрос конечно же смешной, но как эти данные привязать к элементу на форме, DataGridView например ? В Аксе надо было прописывать RowSource, а здесь как? Может есть несколько вариантов. Все советы приветствуются.

  Ответить  
 
 автор: Мюллер   (23.03.2010 в 14:44)   личное сообщение
 
 

Я уже здесь выкладывал пример привязки данных к гриду. Для этого нужно использовать объект DataSet


Using cn As New SqlConnection(strConn) 'Строка подключения
cn.Open()
Dim cmd As SqlCommand
cmd = New SqlCommand(strSQL1, cn)

Dim da1 As New SqlDataAdapter(cmd)
Dim ds1 As New DataSet()
da1.Fill(ds1)

Me.DataGrid1.DataSource = ds1
Me.DataGrid1.DataBind()

cmd.Connection.Close()
cmd.Connection.Dispose()

End Using

  Ответить  
 
 автор: Мюллер   (23.03.2010 в 14:51)   личное сообщение
 
 

Лучше использовать для подключения коннектион стринг билдер.
Прописав его один раз в отдельном классе, потом можно вызыватьв формах

Вот пример заполнения комбобока с использованием SqlConnectionStringBuilder-а





Imports System.Data.SqlClient.SqlConnectionStringBuilder
.........

Dim conn As New SqlConnectionStringBuilder()
conn.DataSource = имя сервера
conn.InitialCatalog = имя базы
conn.IntegratedSecurity = True

Using cn As New SqlConnection(conn.ConnectionString)
cn.Open()
strSQL = " SELECT * FROM TblMyTable "
Dim da1 As New SqlDataAdapter(strSQL, cn)
Dim ds1 As New DataSet()
da1.Fill(ds1, "TblMyTable ")

With ds1
Me.ComboBox1.DataSource = .Tables("TblMyTable ")
Me.ComboBox1.DisplayMember = "Name"
Me.ComboBox1.ValueMember = "Id"
End With
End Using

  Ответить  
 
 автор: Едрёныч   (23.03.2010 в 16:46)   личное сообщение
 
 

Покопался по форумам и заработало следующим образом:

Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient

Public Class Form2
Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strConn, strSQL1 As String
strConn = "Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated Security=True;Asynchronous Processing=True;"
strSQL1 = "Select OrderID, CustomerID, OrderDate, ShippedDate, ShipCity" & _
" From Orders Where ShipCountry='Canada'"
Dim cn As New SqlConnection(strConn)
cn.Open()
Dim cmd As SqlCommand
cmd = New SqlCommand(strSQL1, cn)
Dim da1 As New SqlDataAdapter(cmd)
Dim ds1 As New DataSet()
da1.Fill(ds1, "Orders")
DataGridView1.DataBindings.Add("", (ds1), "Orders")

DataGridView1.DataMember = "Orders"
DataGridView1.DataSource = ds1

cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub

End Class
всё равно тяжело пока, всё надо обмыслить.
Тогда при чём здесь ExecuteReader?
Получается, что примеры неполные или не подходят для 3,5.

  Ответить  
 
 автор: Мюллер   (23.03.2010 в 17:25)   личное сообщение
 
 

Тот кусок кода, который вы выложили в первый раз формирует объект DataReader и наполняет его данными из базы.
С этим объектом (DataReader) далее у вас ничего не происходит. Вы его не читаете и ничего не делаете с данными. По аналогии с аксом - сделали рекордсет, наполнили его, и на этом остановились.
Так, что пример вполне нормальный. И подходит под любую версию .NET

  Ответить  
 
 автор: Мюллер   (23.03.2010 в 17:29)   личное сообщение
 
 

А в том примере, который вы нашли на форуме - у вас открывается соединение, и затем оно не закрывается. А это не есть гуд. В последствии убедитесь в этом.
Настоятельно рекомендую использовать конструкцию
Using соединение

EndUsing
В этом случае конструкция сама позаботится о разрыве соединения.

Дописано:
Тогда при чём здесь ExecuteReader?


Эта команда заполняет объект DataReader

  Ответить  
 
 автор: Едрёныч   (23.03.2010 в 20:13)   личное сообщение
 
 

спасибо за совет, постараюсь разобраться и придерживаться его.

  Ответить  
 
 автор: Едрёныч   (23.03.2010 в 21:10)   личное сообщение
 
 

и вот что в итоге получилось, рабочий пример:

Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient


Public Class форма1

Private Sub форма1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strConn, strSQL1 As String
strConn = "Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated Security=True;" 'Asynchronous Processing=True;"
Using cn As New SqlConnection(strConn) 'Строка подключения
cn.Open()
strSQL1 = "Select OrderID, CustomerID, OrderDate, ShippedDate, ShipCity" & _
" From Orders Where ShipCountry='Canada'"
Dim cmd1 As SqlCommand
cmd1 = New SqlCommand(strSQL1, cn)
Dim da1 As New SqlDataAdapter(cmd1)
Dim ds1 As New DataSet()
da1.Fill(ds1, "Orders")
DataGridView1.DataBindings.Add("", (ds1), "Orders")
DataGridView1.DataMember = "Orders"
Me.DataGridView1.DataSource = ds1
cmd1.Connection.Close()
cmd1.Connection.Dispose()
End Using
End Sub
End Class

  Ответить  
 
 автор: час   (23.03.2010 в 21:20)   личное сообщение
 
 

ООООООО Едрёныч!!!
- по твоим стопам - можно идти и на твоих ошибках учиться
=========================================
Хотя, без Мюллера - оно конечно нифига не получиться

  Ответить  
 
 автор: Едрёныч   (24.03.2010 в 15:34)   личное сообщение
 
 

Покопался в примере выше и привязал ComboBox, вот, получилось:

Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient
Imports System.Data.SqlClient.SqlConnectionStringBuilder
Public Class Form3

Private Sub Form3_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strConn3 As New SqlConnectionStringBuilder()
Dim strSQL3 As String
'strConn3 = "Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated Security=True;"
strConn3.DataSource = ".\SQLExpress"
strConn3.InitialCatalog = "Northwind"
strConn3.IntegratedSecurity = True
Using cn3 As New SqlConnection(strConn3.ConnectionString)
cn3.Open()
strSQL3 = "SELECT DISTINCT CustomerID FROM Orders"
Dim da3 As New SqlDataAdapter(strSQL3, cn3)
Dim ds3 As New DataSet()
da3.Fill(ds3, "Orders")
With ds3
Me.ComboBox1.DataSource = .Tables("Orders")
Me.ComboBox1.DisplayMember = "CustomerID"
End With
End Using
End Sub
End Class

теперь ещё вопрос: как лучше связать два combobox а? В VBA через "SELECT ... "& имяпервого_combobox & "", а здесь как лучше сделать?

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 15:41)   личное сообщение
 
 

Я это делаю через хранимки ( stored procedure ). В качестве параметров передаю значения комбобоксов.
ЗЫ
Такую конструкцию

"SELECT ... "& имяпервого_combobox & ""
в коде формы вообще не желательно использовать.

  Ответить  
 
 автор: Едрёныч   (24.03.2010 в 15:59)   личное сообщение
 
 

те Вы прописываете прямо в SQLServer? А потом вызываете её выполнение их VS?

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 16:20)   личное сообщение
 
 


те Вы прописываете прямо в SQLServer? А потом вызываете её выполнение их VS?


Да.

Вот пример как вообще нужно правильно делать:

Вот хранимая процедура


CREATE PROCEDURE _spObl
@IdCountry int

AS

SELECT DISTINCT IdObl, OblName FROM TblKlassCity WHERE IdCountry = @IdCountry

/* SET NOCOUNT ON */
RETURN



Далее создается пользовательский класс

(Сорри за код на C#, но лень переписывать на VB)



using System.Data.SqlClient;

public class TranspProvider
{
public TranspProvider()
{
}

public DataSet DSObl(int DDlist) //- Создается ф-ция, возвращающая объект ДатаСет. В качестве принимаемого параметра используется целое число - значение из первого комбобокса
{
ConnClass st = new ConnClass();
using (SqlConnection cn = new SqlConnection(st.strConn()))
{
SqlCommand cmd = new SqlCommand("_spObl", cn);
- вызывается созданная выше хранимая процедура
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@IdCountry", DDlist);
- ей передается параметр - целое число, равное значению первого комбобокса

Далее создаем и заполняем Датасет

cn.Open();
SqlDataAdapter daObl = new SqlDataAdapter(cmd);
DataSet dsObl = new DataSet();
daObl.Fill(dsObl);
cmd.Connection.Close();
cmd.Connection.Dispose();

return dsObl;
- возвращаем датасет
}
}
}


А затем в коде прописываем



......

TranspProvider [b]TransProvider = new TranspProvider(); [/b]- создаем экземпляр TransProvider нашего пользовательского класса
........

Combo2.DataSource = TransProvider.DSObl(Convert.ToInt32 Combo1.SelectedValue)); - вызываем ф-цию DSObl из нашего пользовательского класса. В качестве входного параметра передается значение первого комбобоксаПоскольку результатом выполнения ф-ции является датасет, то делаем его источником для нашего комбобокса.
Combo2.DataTextField = "OblName";
Combo2.DataValueField = "IdObl";
Combo2.DataBind();
...............

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 16:04)   личное сообщение
 
 

О, блин, тока сейчас заметил.
Добавьте строку
ComboBox1.ValueMember = "Числовой Код, по которому будут выбираться значения"

По логике у вас должно быть что-то вроде
Me.ComboBox1.DataSource = .Tables("Orders")
Me.ComboBox1.DisplayMember = "CustomerName" -название клиента
ComboBox1.ValueMember ="CustomerID" - ID клиента

  Ответить  
 
 автор: Едрёныч   (24.03.2010 в 16:09)   личное сообщение
 
 

Не получится, сначала так и было. Выдаёт ошибку насчёт ValueMember. Пришлось редактировать.

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 16:21)   личное сообщение
 
 

Естественно выдаст. Вы же в селекте выбираете только CustomerID.

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 16:53)   личное сообщение
 
 

Вот, все же не поленился переписать классы на VB



Imports System.Data.SqlClient.SqlConnectionStringBuilder
Imports System.Data.SqlClient
Imports System.Windows.Forms.Form
Imports System.Data
Imports System.Data.DataSet
Imports System.Data.DataColumn

Public Class Class1

Public Function DSObl(ByVal DDlist As Integer) As DataSet
Dim strConn3 As New SqlConnectionStringBuilder()
strConn3.DataSource = ".\SQLExpress"
strConn3.InitialCatalog = "Имя базы"
strConn3.IntegratedSecurity = True
Using cn3 As New SqlConnection(strConn3.ConnectionString)

Dim cmd As New SqlCommand("_spObl", cn3)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("@IdCountry", DDlist)
cn3.Open()
Dim daObl As New SqlDataAdapter(cmd)
Dim ds As New DataSet()
daObl.Fill(ds, "Obl")
cmd.Connection.Close()
cmd.Connection.Dispose()
Return ds
End Using

End Function



End Class



И далее на форме


Imports System.Drawing
Imports System.Data.SqlClient.SqlConnectionStringBuilder
Imports System.Data.SqlClient
Imports System.Windows.Forms.Form
Imports System.Data
Imports System.Data.DataSet
Imports System.Data.DataColumn

Public Class Form1

Dim dsprov As New Class1

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim myds As New DataSet()
myds = dsprov.DSObl(Me.ComboBox1.SelectedValue)
With myds
Me.ComboBox1.DataSource = .Tables("Obl")
Me.ComboBox1.DisplayMember = "OblName"
Me.ComboBox1.ValueMember = "IdObl"
End With
End Sub
........

End Class




Текс хранимки остается таким же

  Ответить  
 
 автор: Едрёныч   (24.03.2010 в 17:16)   личное сообщение
 
 

Большое спасибо. Сам бы я нескоро к этому пришёл. Из ваших сообщений я понял, что связывать элементы управления лучше через stored procedure. Буду ковырять. Ещё раз СПАСИБО!!!

  Ответить  
 
 автор: Мюллер   (24.03.2010 в 17:36)   личное сообщение
 
 


Из ваших сообщений я понял, что связывать элементы управления лучше через stored procedure



Не только связывать элементы. Желательно все запросы с параметрами реализовывать через хранимые процедуры.

  Ответить  
 
 автор: Едрёныч   (26.03.2010 в 14:50)   личное сообщение
 
 

а насколько в этом может помочь LINQ toSQL?

  Ответить  
 
 автор: Мюллер   (26.03.2010 в 17:57)   личное сообщение
 
 

Насколько сможет помочь - не знаю. Только не понятно - нафига козе баян?
Освойте сначала ADO.NET - а затем уже лезьте в LINQ. Хотя, конечно, решать вам.
Но без знаний и понимания принципов ADO.NET - в LINQ делать нечего, как в прочем и в .NET

  Ответить  
 
 автор: Едрёныч   (26.03.2010 в 18:43)   личное сообщение
 
 

Понятно.

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList