WebAPI [FromBody] как EF Model ведет себя как неизменный - PullRequest
0 голосов
/ 01 мая 2018

У меня есть контроллер WebAPI, который использует сложные типы из Entity Framework. Когда я получаю объект, я проверяю, существует ли он. Если это не так, я бы хотел создать новый. Прежде чем создавать новый, я бы хотел добавить пару дополнительных значений к объекту. Если я добавлю точку останова и часы, я смогу увидеть значение, и кажется, что оно изменилось. Но значение не попадает в базу данных.

[Authorize(Roles ="customerprofileuser")]
[Route("api/CustomerProfile/Save")]
[HttpPost]
public IHttpActionResult SaveCustomerProfile([FromBody] MERP.Customer _input)
{
    Models.Message.Response _return = new Models.Message.Response();
    _return.Message = "Profile Saved!";
    _return.Now = DateTime.Now;

    try {
        ERPEntities ent = new ERPEntities();
        var cust = ent.Customers.AsNoTracking().Where(w => w.ID == _input.ID).FirstOrDefault();

        if (cust == null)
        {
            _input.ID = Guid.NewGuid();
            _input.Alias = getCustomerNumberNext(_input.Type);
            _input.CreatedOn = DateTime.Now;

            ent.Customers.Add(_input);
        }
        else
        {
            ent.Customers.Attach(_input);
            ent.Entry(_input).State = System.Data.Entity.EntityState.Modified;
        }
        _return.ResponseObject = _input.ID.ToString();
        ent.SaveChanges();
    }
    catch (Exception ex)
    {
        _return.Message = ex.Message;
        _return.Severity = 3;
    }
    return Ok(_return);
}

Если я сопоставлю значения новому объекту, как это, все будет работать как положено.

                var val = new Customer();
                val.ID = Guid.NewGuid();
                val.Active = _input.Active;
                val.Alias = getCustomerNumberNext(_input.Type);
                val.CreatedOn = DateTime.Now;

                ent.Customers.Add(val);

Я бы предпочел не сопоставлять каждое свойство новому свойству объекта. Есть ли способ обойти это поведение?

Вот образец автоматически сгенерированного класса Customer из моей Entity Model.

public partial class Customer
{
    public System.Guid ID { get; set; }
    public string Name { get; set; }
    public Nullable<System.Guid> Type { get; set; }
    public string Alias { get; set; }
    public string Website { get; set; }
    public string Note { get; set; }
    public string Email { get; set; }
    public Nullable<System.Guid> Salesman { get; set; }
    public Nullable<System.Guid> SalesRegion { get; set; }
    public Nullable<bool> Active { get; set; }
    public string LinkedIn { get; set; }
    public string Facebook { get; set; }
    public string Twitter { get; set; }
    public string GoldmineFK { get; set; }
    public string SalesFK { get; set; }
    public string InventoryFK { get; set; }
    public Nullable<System.Guid> Industry { get; set; }
    public Nullable<System.Guid> Lead { get; set; }
    public Nullable<System.Guid> Show { get; set; }
    public Nullable<System.Guid> Territory { get; set; }
    public Nullable<System.DateTime> CreatedOn { get; set; }
}

Вот функция getCustomerNumberNext

    private string getCustomerNumberNext(Guid? companyid)
    {
        ERPEntities ent = new ERPEntities();
        var _prefix = (from p in ent.CompanyLookups
                       where p.Type == "CustomerNumberPrefix"
                       select p.Value.ToString()).FirstOrDefault();

        var _number = (from p in ent.CompanyLookups
                       where p.Type == "CustomerNumberSequence"
                       select p.Value.ToString()).FirstOrDefault();

        var _newNumber = Convert.ToInt32(_number) + 1;

        try
        {
            var _update = (from p in ent.CompanyLookups
                           where p.Type == "CustomerNumberSequence"
                           select p).FirstOrDefault();
            _update.Value = _newNumber.ToString();
            ent.SaveChanges();
        }
        catch (Exception ex)
        { return ex.Message; }

        return _prefix + _number;
    }

РЕДАКТИРОВАТЬ: код C # работает как ожидалось. Проблема была связана с отключением данных от клиента и неполностью.

1 Ответ

0 голосов
/ 01 мая 2018

Я полагаю, что в вашем вопросе есть опечатка, которая гласит, что «попадает в базу данных», но я думаю, что вы имели в виду «не попадает в базу данных»

С этим предположением я попытался запустить подобный код локально и смог сохранить значения, как и ожидалось. Основное отличие состоит в том, что в моем коде псевдоним является целым числом, и я предполагаю, что это сложный класс в вашем коде. Вот код, который успешно сохранил значения в базе данных,

public class HomeController : ApiController
{
    [HttpPost]
    [Route("api/CustomerProfile/Save")]
    public IHttpActionResult SaveCustomerProfile([FromBody] Customer _input)
    {
        masterEntities masterEntities = new masterEntities();
        var cust = masterEntities.Customers.AsNoTracking().Where(w => w.ID == _input.ID).FirstOrDefault();

        if (cust == null)
        {
            _input.ID = Guid.NewGuid();
            _input.Alias = 0;
            _input.CreatedOn = DateTime.Now;

            masterEntities.Customers.Add(_input);
        }
        else
        {
            masterEntities.Customers.Attach(_input);
            masterEntities.Entry(_input).State = System.Data.Entity.EntityState.Modified;
        }

        masterEntities.SaveChanges();

        return Ok();
    }
}

Вот как создается класс Customer,

public partial class Customer
{
    public System.Guid ID { get; set; }
    public bool Active { get; set; }
    public Nullable<int> Alias { get; set; }
    public Nullable<System.DateTime> CreatedOn { get; set; }
}

Можете ли вы обновить свой вопрос с помощью классов Customer и Alias ​​из своего кода, и я могу попробовать воспроизвести это?

На заметку, я бы предложил изменить

var cust = ent.Customers.AsNoTracking().Where(w => w.ID == _input.ID).FirstOrDefault();

до

var cust = ent.Customers.AsNoTracking().FirstOrDefault(w => w.ID == _input.ID);
...