Inquiridor
Atualizar dados do Banco através do DataSet

Pergunta
-
Ola pessoal, preciso atualizar o banco de dados (Insert, Update, Delete) atavez de um DataSet mas não estou conseguindo. Recebo a seguinte mensagem:
Não há suporte para geração SQL dinâmica para UpdateCommand em SelectCommand que não retorne informações importantes de coluna.
Veja como esta o meu codigo
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using Agili;
namespace WindowsFormsApplication10
{
public partial class Form1 : Form
{
DataSet ds;
OleDbDataAdapter da;
_clConexaoBanco conexao;
OleDbCommandBuilder cb;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
conexao = new _clConexaoBanco();
da = new OleDbDataAdapter("Select idTeste, nmTeste, vlTeste, dtCadastro From tblTeste",conexao.conexao);
cb = new OleDbCommandBuilder(da);
ds = new DataSet("Teste");
da.FillSchema(ds, SchemaType.Mapped, "Teste");
da.Fill(ds, "Teste");
DataColumn[] dc = new DataColumn[1];
dc[0] = ds.Tables[0].Columns["idTeste"];
ds.Tables["Teste"].PrimaryKey = dc;
da.InsertCommand = cb.GetInsertCommand();
// Esta dando erro nesta linha
da.UpdateCommand = cb.GetUpdateCommand();
da.DeleteCommand = cb.GetDeleteCommand();
}
private void btnInserir_Click(object sender, EventArgs e)
{
DataRow dr;
dr = ds.Tables[0].NewRow();
dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
ds.Tables[0].Rows.Add(dr);
da.Update(ds,"Teste");
}
private void btnAlterar_Click(object sender, EventArgs e)
{
DataRow dr;
dr = ds.Tables["Teste"].Rows[0];
dr.BeginEdit();
//dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
dr.EndEdit();
da.Update(ds,"Teste");
}
private void btnExcluir_Click(object sender, EventArgs e)
{
ds.Tables[0].Rows[0].Delete();
da.Update(ds);
}
}
}
A chave primaria da tabela é o campo idTeste.
Qual é o erro?
Todas as Respostas
-
-
Sim, o select esta retornando todos os campos da tabela, o interessante é que consigo fazer o insert mas o update não. Veja como esta o código:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using Agili;
namespace WindowsFormsApplication10
{
public partial class Form1 : Form
{
DataSet ds;
OleDbDataAdapter da;
_clConexaoBanco conexao;
OleDbCommandBuilder cb;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
conexao = new _clConexaoBanco();
da = new OleDbDataAdapter("Select idTeste, nmTeste, vlTeste, dtCadastro From tblTeste",conexao.conexao);
ds = new DataSet("Teste");
da.FillSchema(ds, SchemaType.Source, "Teste");
cb = new OleDbCommandBuilder(da);
da.Fill(ds, "Teste");
//DataColumn[] dc = new DataColumn[1];
//dc[0] = ds.Tables[0].Columns["idTeste"];
//ds.Tables["Teste"].PrimaryKey = dc;
}
private void btnInserir_Click(object sender, EventArgs e)
{
DataRow dr;
dr = ds.Tables[0].NewRow();
dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
ds.Tables[0].Rows.Add(dr);
da.Update(ds,"Teste");
}
private void btnAlterar_Click(object sender, EventArgs e)
{
DataRow dr;
dr = ds.Tables["Teste"].Rows[0];
dr.BeginEdit();
//dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
dr.EndEdit();
da.Update(ds,"Teste");
}
private void btnExcluir_Click(object sender, EventArgs e)
{
ds.Tables[0].Rows[0].Delete();
da.Update(ds);
}
}
}
-
Tente fazer o seguinte, ao invez de nomear os campo use * assim garantimos que tudo esta sendo carregado.
Tambem arrume a a propriedade do dataAdapter "MissingSchemaAction" para "AddWithKey".
Se isso funcionar, remova o * e arrume as colunas de acordo com o que você realmente precisa.
Binding you through life - Se serve, marque!!! -
Fiz as mudanças que vc falou, mas agora ele esta dando esta mensagem de erro quando chamo o metodo Update do DataAdapter
Não há suporte para geração SQL dinâmica para UpdateCommand em SelectCommand que não retorne informações importantes de coluna.
-
Marcio,
Posso estar falando bobagem mas de acordo com http://msdn.microsoft.com/pt-br/library/system.data.oledb.oledbcommandbuilder.aspx
o comando dataAdapter.Update() não iria funcionar se vc nao tiver um CommandBuilder no código.
Veja esse código tirado da página:
public static DataSet UpdateRows(string connectionString, string queryString, string tableName) { DataSet dataSet = new DataSet(); using (OleDbConnection connection = new OleDbConnection(connectionString)) { OleDbDataAdapter adapter = new OleDbDataAdapter(); adapter.SelectCommand = new OleDbCommand(queryString, connection); OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter); connection.Open(); adapter.Fill(dataSet, tableName); //code to modify data in DataSet here cb.GetDeleteCommand(); //Without the OleDbCommandBuilder this line would fail adapter.Update(dataSet, tableName); connection.Close(); } return dataSet; }
Não sei como seu Insert está funcionando, mas enfim, tente criar um CommandBuilder e ver se dá certo! -
-
-
Quando fiz isso (da.UpdateCommand = cb.GetUpdateCommand();) ele me deu o seguinte erro ao executar esta linha:
Não há suporte para geração SQL dinâmica para UpdateCommand em SelectCommand que não retorne informações importantes de coluna.
O que pode ser? -
da.UpdateCommand = new OledbCommand(String.Format("UPDATE tabela SET campo1={0}, campo2={1}, campo3={2} WHERE campoID={3}",dr["nmTeste"],dr["vlTeste"],dr["dtCadastro"],dr["idTeste"]));
Não esqueça de fazer as tranformações ex: Convert.toDateTime(dr["dtCadastro"]) e etc
edit: acho q não vai precisar faze os converts pq depois vai td como string
Ve se dá certo- Editado Reinaldo Camargo segunda-feira, 24 de agosto de 2009 19:12 ver edit
-
-
Reinaldo testei aqui mas no meu caso é inviável esta tecnica pois a casos onde o dataset tem muitas alteraçoes, inclusões e deleçoes desta forma eu tenho que fazer um loop no dataset para saber o tipo de alteração e disparar o método adequado. Eu preciso usar uma forma mais automática ou seja quando eu executar o método Update do adapter ele aplica todas as alteraçoes no banco. Sei que preciso definir os comandos para insert, update e delete no adapter mas preciso que isso fique mais dinamico.
Voce me entende ? -
Acredito que o problema esta na forma como a query de select foi definida, mas como não conseguimos decobrir o problem, defina a query de update na mão e atribua a mesma manualmente à propriedado do DataAdapter
Binding you through life - Se serve, marque!!! -
Eu fiz assim, aparentemente não deu erro em nada, mas também atualizou nada no banco.
private void btnAlterar_Click(object sender, EventArgs e)
{
string strConexao = "Provider=OraOLEDB.Oracle.1;Password=dbdsvphoenix;Persist Security Info=True;User ID=dbdsvphoenix;Data Source=PROD";
OleDbConnection conexao = new OleDbConnection(strConexao);
string strUpdate;
da = new OleDbDataAdapter("Select idTeste, nmTeste, vlTeste, dtCadastro From tblTeste", conexao);
ds = new DataSet("Teste");
da.Fill(ds, "Teste");
strUpdate = "Update tblTeste set nmTeste = @nmTeste, vlTeste = @vlTeste, dtCadastro = @dtCadastro Where idTeste = @idTeste";
da.UpdateCommand = new OleDbCommand(strUpdate);
da.UpdateCommand.Parameters.Add("@nmTeste", OleDbType.VarChar, 100, "nmTeste");
da.UpdateCommand.Parameters.Add("@vlTeste", OleDbType.Double, 10, "vlTeste");
da.UpdateCommand.Parameters.Add("@dtCadastro", OleDbType.Date, 15, "dtCadastro");
da.UpdateCommand.Parameters.Add("@idTeste", OleDbType.Integer, 10, "idTeste");
da.UpdateCommand.Connection = conexao;
DataRow dr;
dr = ds.Tables["Teste"].Rows[0];
dr.BeginEdit();
//dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
dr.EndEdit();
ds.AcceptChanges();
da.Update(ds,"Teste");
}
-
-
-
-
Ha, mas por que o insert funciona, veja o código:
private void btnInserir_Click(object sender, EventArgs e)
{
DataRow dr;
dr = ds.Tables[0].NewRow();
dr["idTeste"] = txtId.Text;
dr["nmTeste"] = txtNome.Text;
dr["vlTeste"] = txtValor.Text;
dr["dtCadastro"] = txtData.Text;
ds.Tables[0].Rows.Add(dr);
da.Update(ds,"Teste");
-
-
-
-
-
-
Sim, ela possui e no select ela esta vindo
A minha tabela é esta:
IDTESTE NUMBER(10) -> Chave Primaria
NMTESTE VARCHAR2(50) Y
VLTESTE NUMBER(10,2) Y
DTCADASTRO DATE Y
eo select que estou passando para o Adapter é este:
Select idTeste, nmTeste, vlTeste, dtCadastro From Teste -
O que esta acontecendo aparentemente é que quando o update vai acontecer ele não consegue definir qual é a chave primaria e sem a chave primaria ele não pode garantir que apenas um registro vai ser alterado então ele falha.
Tente o seguinte,
Após preexncher sua tabela no DataSet defina manualmente a coluna da chave primaria.
Algo assimTable oneTable = ds.Tables[0] oneTable.PrimaryKey = oneTable.Columns["idTeste"]
Acho que é assim, fiz o codigo fora do VS, então testa ae.
Binding you through life - Se serve, marque!!! -
-
-
-
-
Vamos la,
cb = new OleDbCommandBuilder(da); da.MissingSchemaAction = MissingSchemaAction.AddWithKey; da.FillSchema(ds, SchemaType.Source); DataColumn[] dc = new DataColumn[1]; dc[0] = ds.Tables[0].Columns["idTeste"]; ds.Tables["Teste"].PrimaryKey = dc; da.Fill(ds, "Teste");
Tente alterar desta maneira.
Veja tambem o que achei na documentação
Adds the necessary columns and primary key information to complete the schema. For more information about how primary key information is added to a DataTable, see FillSchema.To function properly with the .NET Framework Data Provider for OLE DB, AddWithKey requires that the native OLE DB provider obtains necessary primary key information by setting the DBPROP_UNIQUEROWS property, and then determines which columns are primary key columns by examining DBCOLUMN_KEYCOLUMN in the IColumnsRowset. As an alternative, the user may explicitly set the primary key constraints on each DataTable. This ensures that incoming records that match existing records are updated instead of appended. When using AddWithKey, the .NET Framework Data Provider for SQL Server appends a FOR BROWSE clause to the statement being executed. The user should be aware of potential side effects, such as interference with the use of SET FMTONLY ON statements. See SQL Server Books Online for more information.
Binding you through life - Se serve, marque!!! -
Bom dia ViewState
Refiz o código como voce sugeriu mas o erro continua, na verdade eu ja tinha feito isso como voce pode ver no código acima e mesmo assim continua dando a mensagem de erro:
Não há suporte para geração SQL dinâmica para UpdateCommand em SelectCommand que não retorne informações importantes de coluna.
Não sei mais o que fazer, ja estou ficando louco hahaha, so com bom humor mesmo.
vou continuar pesquisando e testando mas estou chegando a conclusão que isso não vai ser possível.
se voce tiver outra sugestão estou aceitando. -
-
Se o provider funcionar direitinho pra Oracle manda bala,
http://www.codeplex.com/LinqToOracle
Tai o link.
Binding you through life - Se serve, marque!!! -
-
-
-
Não, Linq travalho com sabores, LINQ to SQL, LINQ to ORACLE, LINQ to Entities e assim vai.
Um sugestão, é trabalhar com commands, esquece o DataAdapter e DataSet, faça as coisa na mão. Ou use algo como NHibernate, ou CodeSmith pra gerar seu codigo.
Binding you through life - Se serve, marque!!!