简体   繁体   中英

Database not updated bug - Entity Framework

I am using a Entity Framework and JQuery to update values in an SQL table column with a bit data type. This is being done by reading the values into an html table and then having a button that will change the bit value for each row.

Here you can see the html table:

    <table id="categoryList" class="table">
    <thead>
    <tr>
        <th>Category ID</th>
        <th>Category Name</th>
    </tr>
    </thead>
    <tbody>
    @foreach (var item in Model.Categories)
    {
        <tr>
            <td>@item.id</td>
            <td>@item.name</td>
            <td>
                <button class="btn btn-success categoryEnabled" data-id="@item.id">Enabled</button>
            </td>
        </tr>
    }
    </tbody>
</table>

Then here is the script I am using to start the action on click:

$(".categoryEnabled").on("click", function() {
    $(this).hide();
    $(this).next().show();
    if (!e) var e = window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) {
        e.stopPropagation();
    }
    DisableRow($(this).data('id'));
});

function DisableRow(id) {
    $.post('@Url.Action("DisableRow", "Category")', { "Id": id }, function () {
        alert('Row Disabled!');
    }).fail(function () {
        alert('Error disabling row!');
    });
}

This is then linked to a controller action that should change the state bit value for the selected row and update:

public void DisableRow(int id)
    {
        var connection = new CategoryDBEntities();

        var record = connection.Categories.Find(id);

        if (record == null) return;

        record.state = StatesTypes.Disabled;

        connection.SaveChanges();
    }

Here's Category object for reference:

namespace Project.Models
{
using System;
using System.Collections.Generic;

    public enum StatesTypes
    {
        Disabled = 0,
        Enabled = 1
    }

public partial class Category
{

    public int id { get; set; }
    public string name { get; set; }
    public StatesTypes state { get; set; }
}

}

DbContext:

namespace Project.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

public partial class CategoryDBEntities : DbContext
{
    public QualityDBEntities()
        : base("name=CategoryDBEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public DbSet<Category> Categories { get; set; }

}

}

Output from Diagnostics Debug:

SELECT TOP (2) 
[Extent1].[id] AS [id], 
[Extent1].[name] AS [name]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[id] = @p0


-- p0: '5' (Type = Int32)

The issue is that the record.state is changed to disabled (0), but the bit value in the database does not change. I must be missing something here. Thanks for your help!

Your state column is not being mapped at all between EF and your database.

You can see this in your SQL log:

SELECT TOP (2) 
[Extent1].[id] AS [id], 
[Extent1].[name] AS [name]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[id] = @p0


-- p0: '5' (Type = Int32)

Notice that the state column is not being selected at all.

Look to see if you have configured the state property to be ignored by using an annotation [NotMapped] , or fluent API configuration like entityTypeConfiguration.Ignore(p => p.state) .

Once you have that fixed, I expect you'll be getting exceptions about the fact that you're mapping an enum to a bit field. As others are suggesting, you probably want to use a boolean for your property.

I will make this an answer because I am pretty sure if you are hitting the action method at some point you will need to do this before saving changes.

connection.Entry(record).State = EntityState.Modified;
connection.SaveChanges();    

This allows EF to issue an update on the record passed. I still think you might run into issues not having the state be a boolean and trying to save to a bit field though.

Humor us and try the following:

public void DisableRow(int id)
{
    var connection = new CategoryDBEntities();

    var record = connection.Categories.Find(id);

    if (record == null) return;

    record.state = false; //Assume false for disabled

    connection.SaveChanges();
}

And

public partial class Category
{
    public int id { get; set; }
    public string name { get; set; }
    public bool state { get; set; }
}

I am making the assumption you are using code first to create your database, but regardless I know for a fact if you generate from an existing DB the field will be a bool if it is a bit in the db. Something else to consider it might need to be a nullable column on the DB unless you set a default some how. Simply replace:

public bool state { get; set; }
//with
public bool? state { get; set; }

It doesn't look like you're actually committing the changed item back to the database. You're only altering the copy you've made of it.

To ensure that the data is altered in the DB you want to do something like the following:

connection.Categories.Attach(record);
connection.Entry(record).State = System.Data.Entity.EntityState.Modified;
connection.SaveChanges();

Finally got this figured out! Thanks @Shawn for all the help!

There were actually a couple things going on.

First off, like you suggested I had to change the the StatesType enum to bool so it would map correctly:

public partial class Category
{
public int id { get; set; }
public string name { get; set; }
public bool state { get; set; }
}

Since its now bool I set the state to false:

public void DisableRow(int id)
{
var connection = new CategoryDBEntities();

var record = connection.Categories.Find(id);

if (record == null) return;

record.state = false;

connection.SaveChanges();
}

The big issue here and the main reason that it wasn't showing any change in the database was because the state column was not being mapped between EF and the database (which was also referenced in one of the answers).

This was because the state column was created in SQL Server Management; not VS. So I had to go into the .edmx and click 'Update Model from Database' and then refresh the table.

Thanks for all the help on this one!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM