Как использовать строку в качестве первичного ключа в MVC 3 Entity Framework 4.1 Code First? - PullRequest
1 голос
/ 15 июля 2011

Сначала я использую последний и самый лучший код Entity Framework, и я сталкиваюсь со сценарием, в котором я хочу, чтобы один из моих классов использовал строку для первичного ключа.Мне пришлось вручную добавить ключ в представление «Создать» (по умолчанию он обрабатывает его как личность).Однако, когда я пытаюсь создать новый MyAccount , я получаю сообщение об ошибке ниже.Я использую шаблон репозитория MVC Scaffolder для создания MyAccountController.Вашу мудрость я с большой благодарностью ищу.

Модель:

public class MyAccount 
{
    [Key, Required, MaxLength(80), Display(Name = "User name")]   
    public string UserName { get; set; }

    [Required, DataType(DataType.EmailAddress), MaxLength(100), Display(Name = "Email address")]   
    public string Email { get; set; } 
}

Вид:

<% using (Html.BeginForm()) { %>
    <%: Html.ValidationSummary(true) %>
    <legend>MyAccount</legend>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.UserName) %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.UserName) %>
            <%: Html.ValidationMessageFor(model => model.UserName)%>
        </div>
        <%: Html.Partial("CreateOrEdit", Model) %>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
<% } %>

Контроллер:

    //
    // GET: /MyAccount/Create

    public ActionResult Create()
    {
        return View();
    } 

    //
    // POST: /MyAccount/Create

    [HttpPost]
    public ActionResult Create(MyAccount myaccount)
    {
        if (ModelState.IsValid) {
            myaccountRepository.InsertOrUpdate(myaccount);
            myaccountRepository.Save();
            return RedirectToAction("Index");
        } else {
            return View();
        }
    }

Хранилище:

public class MyAccountRepository : IMyAccountRepository
{
    Par4ScoreContext context = new Par4ScoreContext();

    public IQueryable<MyAccount> All
    {
        get { return context.MyAccounts; }
    }

    public IQueryable<MyAccount> AllIncluding(params Expression<Func<MyAccount, object>>[] includeProperties)
    {
        IQueryable<MyAccount> query = context.MyAccounts;
        foreach (var includeProperty in includeProperties) {
            query = query.Include(includeProperty);
        }
        return query;
    }

    public MyAccount Find(string id)
    {
        return context.MyAccounts.Find(id);
    }

    public void InsertOrUpdate(MyAccount myaccount)
    {
        if (myaccount.UserName == default(string)) {
            // New entity
            context.MyAccounts.Add(myaccount);
        } else {
            // Existing entity
            context.Entry(myaccount).State = EntityState.Modified;
        }
    }

    public void Delete(string id)
    {
        var myaccount = context.MyAccounts.Find(id);
        context.MyAccounts.Remove(myaccount);
    }

    public void Save()
    {
        context.SaveChanges();
    }
}

public interface IMyAccountRepository
{
    IQueryable<PlayerAccount> All { get; }
    IQueryable<PlayerAccount> AllIncluding(params Expression<Func<MyAccount, object>>[] includeProperties);
    MyAccount Find(string id);
    void InsertOrUpdate(MyAccount playeraccount);
    void Delete(string id);
    void Save();
}

Ошибка в MyAccountRepository.Save ():

System.Data.Entity.Infrastructure.DbUpdateConcurrencyException was unhandled by user code:  
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
StackTrace:
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at MyProject.Models.MyAccountRepository.Save() 

....

InnerException: System.Data.OptimisticConcurrencyException
Message=Store update, insert, or delete statement affected an unexpected number of rows (0).    
Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Source=System.Data.Entity
StackTrace:
    at System.Data.Mapping.Update.Internal.UpdateTranslator.ValidateRowsAffected(Int64 rowsAffected, UpdateCommand source)
    at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
    at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
    at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
    at System.Data.Entity.Internal.InternalContext.SaveChanges()

1 Ответ

1 голос
/ 25 июля 2011

Поскольку связыватель модели MVC назначит пустую строку для UserName, вы можете проверить, является ли она новой или нет, используя string.IsNulOrEmpty(playeraccount.UserName). Вы можете использовать IsNullOrWhiteSpace , если вы рассматриваете пробелы как пустые.

public void InsertOrUpdate(MyAccount myaccount)
{
    if (string.IsNulOrEmpty(myaccount.UserName)) {
        // New entity
        context.MyAccounts.Add(myaccount);
    } else {
        // Existing entity
        context.Entry(myaccount).State = EntityState.Modified;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...