3

我正在开发一个用于出租物业的 mvc 应用程序。

模型 Imovel(房地产)

namespace Imobiliario.Models
{
    [Table("Imoveis")]
    public class Imovel
    {
        [Key]
        public int ImovelID { get; set; }

        [DisplayName("Tipo Cômodo")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public int TipoComodoID { get; set; }
        public virtual TipoComodo TipoComodo { get; set; }

        [DisplayName("Endereço")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public int EnderecoID { get; set; }
        public virtual Endereco Endereco { get; set; }

        [DisplayName("Quantidade de cômodos")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public int QtdComodos { get; set; }

        [DisplayName("Quantidade de banheiros")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public int QtdBanheiros { get; set; }

        [DisplayName("Alugado")]
        public bool Alugado { get; set; }

        [DisplayName("Valor do aluguel")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public decimal ValorAluguel { get; set; }

        public virtual ICollection<DetalhesImovel> DetalhesImovel { get; set; }
        public virtual ICollection<Imagem> Imagens { get; set; } 
        public virtual ICollection<Taxa> TaxasList { get; set; }

        [ConcurrencyCheck]
        [Timestamp]
        public Byte[] Timestamp { get; set; }


    }
}

模型 Endereço(地址):

namespace Imobiliario.Models
{
    [Table("Enderecos")]
    public class Endereco
    {

        [Key]
        [ScaffoldColumn(false)]
        public int EnderecoID { get; set; }

        [DisplayName("Logradouro")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public string Logradouro { get; set; }

        [DisplayName("Número")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public int Numero { get; set; }

        [DisplayName("Complemento")]
        public string Complemento { get; set; }

        [DisplayName("Bairro")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public string Bairro { get; set; }

        [DisplayName("Cidade")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public string Cidade { get; set; }

        [DisplayName("Cep")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public string Cep { get; set; }

        [DisplayName("Estado")]
        [Required(ErrorMessage = "Campo obrigatório.")]
        public string Estado { get; set; }
    }
}

模型DetalhesImovel(详情):

namespace Imobiliario.Models
{
    [Table("DetalhesImovel")]
    public class DetalhesImovel
    {
        [Key]
        public int DetalhesImovelID { get; set; }

        [DisplayName("Descrição")]
        public string Descricao { get; set; }

        public string Grupo { get; set; }

        [ScaffoldColumn(false)]
        public DateTime DataCadastro { get; set; }

        public virtual ICollection<Imovel> Imovel { get; set; }

        public override bool Equals(object obj)
        {
            var param = (DetalhesImovel)obj;
            if (DetalhesImovelID == param.DetalhesImovelID || Descricao == param.Descricao)
                return true;
            return false;
        }

    }
}

Imovel控制器:

namespace Imobiliario.Controllers
{
    public class ImoveisController : Controller
    {
        private ImobiliarioDbContext db = new ImobiliarioDbContext();

        //
        // GET: /Imoveis/

        public ActionResult Index(int? id, int? detalhesImovel, int? imagensImovel)
        {
            var viewModel = new IndexImovel();
            viewModel.Imovel =
                db.Imoveis.Include(i => i.DetalhesImovel.Select(d => d.Imovel))
                .Include(i => i.TaxasList.Select(im => im.Imovel))
                .Include(i => i.Imagens.Select(im => im.Imoveis))
                .Include(i => i.TipoComodo)
                .Include(i => i.Endereco)
                .OrderBy(i => i.ImovelID);


            return View(viewModel);
        }

        //
        // GET: /Imoveis/Details/5

        public ActionResult Details(int id = 0)
        {
            var imoveis = db.Imoveis.Include(i => i.DetalhesImovel.Select(d => d.Imovel))
                .Include(i => i.TaxasList.Select(im => im.Imovel))
                .Include(i => i.Imagens.Select(im => im.Imoveis))
                .Include(i => i.TipoComodo)
                .Include(i => i.Endereco)
                .Where(i => i.ImovelID == id)
                .OrderBy(i => i.ImovelID);

            return View(imoveis.ToList());

        }

        //
        // GET: /Imoveis/Create

        public ActionResult Create()
        {
            ViewBag.TipoComodoID = new SelectList(db.TipoComodo, "TipoComodoID", "Descricao");
            var todosDetalhes = db.DetalhesImoveis;
            var viewModel = new List<ImovelDetalhes>();
            foreach (var detalhe in todosDetalhes)
            {
                viewModel.Add(new ImovelDetalhes
                {
                    Descricao = detalhe.Descricao,
                    DetalhesImovelID = detalhe.DetalhesImovelID,
                });
            }
            ViewBag.Detalhes = viewModel;
            return View();
        }

        //
        // POST: /Imoveis/Create

        [HttpPost]
        public ActionResult Create(CreateImovel imo, string[] detalhesSelecionados, int tipoComodoID)
        {
            if (ModelState.IsValid)
            {
                imo.Imovel.TipoComodoID = tipoComodoID;

                db.Enderecos.Add(imo.Endereco);
                db.Imoveis.Add(imo.Imovel);
                foreach (var item in db.DetalhesImoveis)
                {
                    if (detalhesSelecionados.Contains(item.DetalhesImovelID.ToString()))
                    {
                        imo.Imovel.DetalhesImovel = new Collection<DetalhesImovel>();
                        imo.Imovel.DetalhesImovel.Add(item);
                    }
                }
                db.SaveChanges();
                return RedirectToAction("Index");
            }


            return View(imo);
        }

        //
        // GET: /Imoveis/Edit/5

        public ActionResult Edit(int id = 0)
        {
            Imovel imovel =
                db.Imoveis.Include(i => i.DetalhesImovel).Include(i => i.Endereco).Include(i => i.TipoComodo).Include(i => i.TaxasList).Single(
                    i => i.ImovelID == id);
            PopularSeletorDetalhes(imovel);
            PopularDropDownTipoComodo(imovel.TipoComodoID);
            return View(imovel);
        }

        //
        // POST: /Imoveis/Edit/5

        [HttpPost]
        public ActionResult Edit(string[] detalhesSelecionados, Imovel imovel, FormCollection formCollection)
        {
            imovel =
                db.Imoveis.Include(i => i.Endereco).Include(i => i.TipoComodo).Include(i => i.DetalhesImovel).Single(
                    i => i.ImovelID == imovel.ImovelID);
            try
            {

                if (ModelState.IsValid)
                {
                    if (TryUpdateModel(imovel, "", null, new string[] { "DetalhesImovel" }))
                    {

                        AtualizaDetalhesImovel(detalhesSelecionados, imovel);
                        db.Entry(imovel).State = EntityState.Modified;
                        db.SaveChanges();
                        return RedirectToAction("Index");
                    }
                }

            }
            catch (DbUpdateConcurrencyException ex)
            {
                var entry = ex.Entries.Single();
                var databaseValues = (Imovel)entry.GetDatabaseValues().ToObject();
                var clientValues = (Imovel)entry.Entity;
                if (databaseValues.TipoComodo.Descricao != clientValues.TipoComodo.Descricao)
                    ModelState.AddModelError("TipoComodo", "Valor atual: " + databaseValues.TipoComodo.Descricao);
                if (databaseValues.QtdComodos != clientValues.QtdComodos)
                    ModelState.AddModelError("QtdComodos", "Valor atual: " + String.Format("{0:n}", databaseValues.QtdComodos));
                if (databaseValues.QtdBanheiros != clientValues.QtdBanheiros)
                    ModelState.AddModelError("QtdBanheiros", "Valor atual: " + String.Format("{0:n}", databaseValues.QtdBanheiros));
                if (databaseValues.Alugado != clientValues.Alugado)
                    ModelState.AddModelError("Alugado", "Valor atual: " + databaseValues.Alugado);
                ModelState.AddModelError(string.Empty, "The record you attempted to edit "
                    + "was modified by another user after you got the original value. The "
                    + "edit operation was canceled and the current values in the database "
                    + "have been displayed. If you still want to edit this record, click "
                    + "the Save button again. Otherwise click the Back to List hyperlink.");
                imovel.Timestamp = databaseValues.Timestamp;
            }

            catch (DataException)
            {
                //Log the error (add a variable name after Exception)
                ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
            }
            return View(imovel);
        }

        //
        // GET: /Imoveis/Delete/5

        public ActionResult Delete(int id = 0)
        {
            Imovel imovel = db.Imoveis.Find(id);
            if (imovel == null)
            {
                return HttpNotFound();
            }
            return View(imovel);
        }

        //
        // POST: /Imoveis/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            Imovel imovel = db.Imoveis.Find(id);
            db.Imoveis.Remove(imovel);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        private void PopularDropDownTipoComodo(object tipoComodoSelecionado)
        {
            var tipoComodoQuery = from d in db.TipoComodo
                                  orderby d.Descricao
                                  select d
                                  ;
            ViewBag.TipoComodoId = new SelectList(tipoComodoQuery, "TipoComodoID", "Descricao", tipoComodoSelecionado);
        }

        private void PopularSeletorDetalhes(Imovel imovel)
        {
            var todosDetalhes = db.DetalhesImoveis;
            var detalhesImovel = new HashSet<int>(imovel.DetalhesImovel.Select(t => t.DetalhesImovelID));
            var viewModel = new List<ImovelDetalhes>();
            foreach (var detalhe in todosDetalhes)
            {
                viewModel.Add(new ImovelDetalhes
                                  {
                                      Descricao = detalhe.Descricao,
                                      DetalhesImovelID = detalhe.DetalhesImovelID, 
                                      Seletor = detalhesImovel.Contains(detalhe.DetalhesImovelID)
                                  });
            }
            ViewBag.Detalhes = viewModel;
        }

        private void AtualizaDetalhesImovel(IEnumerable<string> detalhesSelecionados, Imovel imovelAtualizar)
        {
            if (detalhesSelecionados == null)
            {
                imovelAtualizar.DetalhesImovel = new Collection<DetalhesImovel>();
                return;
            }
            var selecaoDetalhesHs = new HashSet<string>(detalhesSelecionados);
            var imovelDetalhes = new HashSet<int>(imovelAtualizar.DetalhesImovel.Select(d => d.DetalhesImovelID));
            foreach (var item in db.DetalhesImoveis)
            {
                if (selecaoDetalhesHs.Contains(item.DetalhesImovelID.ToString(CultureInfo.InvariantCulture)))
                {
                    if (!imovelDetalhes.Contains(item.DetalhesImovelID))
                    {
                        imovelAtualizar.DetalhesImovel.Add(item);
                    }
                }
                else
                {
                    if (imovelDetalhes.Contains(item.DetalhesImovelID))
                    {
                        imovelAtualizar.DetalhesImovel.Remove(item);
                    }
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }



    }
}

编辑.cshtml:

@model Imobiliario.Models.Imovel

@{
    ViewBag.Title = "Editar";
}

<h2>Editar</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Imovel</legend>

        @Html.HiddenFor(model => model.ImovelID)
        @Html.HiddenFor(model => model.Timestamp)
        <div class="editor-label">
            @Html.LabelFor(model => model.TipoComodo)
        </div>
        <div class="editor-field">
            @Html.DropDownList("TipoComodoID", String.Empty)
            @Html.ValidationMessageFor(model => model.TipoComodoID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.QtdComodos)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.QtdComodos)
            @Html.ValidationMessageFor(model => model.QtdComodos)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.QtdBanheiros)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.QtdBanheiros)
            @Html.ValidationMessageFor(model => model.QtdBanheiros)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Alugado)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Alugado)
            @Html.ValidationMessageFor(model => model.Alugado)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ValorAluguel)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ValorAluguel)
            @Html.ValidationMessageFor(model => model.ValorAluguel)
        </div>
        <div class="editor-label">
            @Html.Label("Detalhes Imóvel")
        </div>
        <div class="editor-field">
            <table>
                <tr>
                    @{
                        int cnt = 0;
                        List<Imobiliario.ViewModels.ImovelDetalhes> detalhes = ViewBag.Detalhes;
                        foreach (var imovelDetalhes in detalhes)
                        {
                            if (cnt++ % 4 == 0)
                            {
                                @: </tr> <tr>
                            }
                            @: <td>
                            <input 
                                type="checkbox" 
                                name="detalhesSelecionados" 
                                value="@imovelDetalhes.DetalhesImovelID"@(Html.Raw(imovelDetalhes.Seletor ? "checked=\"checked\"" : ""))/>
                                @imovelDetalhes.Descricao
                               @:</td>
                        }
                        @: </tr>       
                    }
            </table>
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

所有方法都运行良好,但我无法验证并发性。我正在使用 Timestamp,但进行了更改并且并发上没有显示警告消息。

* Q: *问题是验证并发的timestamp的字节加载了不同的值(在浏览器A中,显示的字节为0,0,0,0,0,0,8,7和B浏览器显示的字节数是0,0,0,0,0,0,23,113)所以不处理并发因为值不同。有人可以在我的代码中看到我做错了什么?

我知道 Timestamp 必须携带相同的值才能检查并发性,有人可以帮我解决这个问题吗?

4

0 回答 0