0

I'm developing a C# ASP.NET application, in which i'm retrieving some data from the database, throwing in a form, and when i click on Save, i want it to save my changes in the database.

I'm using Linq to SQL. The code below, at the end, call the method ClienteBusiness.SalvarAlteracoes(cliente), which by the way, only calls the ClienteData.SalvarAlteracoes(cliente) method.

protected void Salvar()
{
    TB_CLIENTE_CLI cliente = new TB_CLIENTE_CLI();

    int idEstado = 0;
    int idCidade = 0;
    if (!Int32.TryParse(ddlEstado.SelectedValue, out idEstado))
    {
        return;
    }
    if (!Int32.TryParse(Request.Form[ddlCidade.UniqueID], out idCidade))
    {
        return;
    }

    cliente.TXT_RAZAOSOCIAL_CLI = txtRazaoSocial.Text;
    cliente.TXT_NOMEFANTASIA_CLI = txtNomeFantasia.Text;
    cliente.TXT_CNPJ_CLI = txtCNPJ.Text;
    cliente.TXT_CEP_CLI = txtCEP.Text;
    /*e os demais campos*/

    //Se a tela for de edição, altera o valor do ID para o cliente correspondente.
    cliente.ID_CLIENTE_CLI = this.IdCliente;

    ClienteBusiness.SalvarAlteracoes(cliente);

    HTMLHelper.jsAlertAndRedirect(this, "Salvo com sucesso!", ResolveUrl("~/Pages/ClientePage.aspx"));
}

The method which save the changes is described below:

public static Int32 SalvarAlteracoes(TB_CLIENTE_CLI cliente)
{
    using (PlanoTesteDataContext context = DataContext.ObterConexao())
    {

        if (cliente.ID_CLIENTE_CLI == 0)
        {
            context.TB_CLIENTE_CLIs.InsertOnSubmit(cliente);
        }
        else
        {
            context.TB_CLIENTE_CLIs.Attach(cliente, true);
        }

        context.SubmitChanges();
    } return cliente.ID_CLIENTE_CLI;
}

On the line context.TB_CLIENTE_CLIs.Attach(cliente, true); i'm receiving a System.InvalidOperationException: An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.

I've already checked the UpdateChecks and they are set to Never.

What can I do? Thanks and sorry for the bad english.

0

2 Answers 2

1

This should work:

else
    {
     context.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, cliente);
     context.TB_CLIENTE_CLIs.Attach(cliente);
   }

This Refresh overload will keep the changes made by the user,it compares the modified entity with the original values from the database, detects the difference and marks the entity as modified and the call to SubmitChanges applies the update to the database.

Sign up to request clarification or add additional context in comments.

3 Comments

Now i have the following exception: DuplicateKeyException: Cannot add an entity with a key that is already in use.
EDIT: Is the above exception related to different instances of Datacontext? (one retrieving the object and other trying to save it?)
@VictorAlencarSantos Try again
0

You may very well run into trouble using Linq2SQL with disconnected entities. EF is a more suited solution to handle this.

However, please ensure you have set all properties on the entity on UpdateCheck to NEVER. I have tested this myself and it works. If this does work it will run an UPDATE statement on every column regardless of whether it has been updated or not. Could cause a problem if you use triggers on your tables. It might be a better idea to use a Timestamp instead to track the entities so concurrency issues between multiple users can be raised.

If you try to Attach an entity from a context where the ObjectTrackingEnabled is not set to False then you will have the following exception thrown:

An unhandled exception of type 'System.NotSupportedException' occurred in System.Data.Linq.dll

Additional information: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.

As an example please use the following for retrieving and reattaching an entity:

    public TB_CLIENTE_CLI Get(int id)
    {
        using (PlanoTesteDataContext ctx = new PlanoTesteDataContext())
        {
            ctx.ObjectTrackingEnabled = false;
            return ctx.TB_CLIENTE_CLI.SingleOrDefault(n => n.ID == id);
        }
    }

    public void Save(TB_CLIENTE_CLI cliente)
    {
        using (PlanoTesteDataContext ctx = new PlanoTesteDataContext())
        {
            ctx.DeferredLoadingEnabled = false;
            ctx.TB_CLIENTE_CLI.Attach(cliente, true);
            ctx.SubmitChanges();
        }
    }

You will also need to set DeferredLoadingEnabled loading to False in the Save method so that you can save down changes on the entity subsequent times after the first initial save on modification.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.