3

よりエレガントなソリューションを作成するために、コレクションを永続化するソリューションについての提案を知りたいと思っています。

DBに保存されたコレクションがあります。このコレクションは、ビューモデルの Web ページに移動します。Web ページからコントローラーに戻ると、変更されたコレクションを同じ DB に永続化する必要があります。

簡単な解決策は、格納されたコレクションを削除して、すべての行を再作成することです。コレクションを混合し、存在しないレコードを削除し、同様のレコードを更新して新しい行を挿入するには、より洗練されたソリューションが必要です。

これは私のモデルとビューモデルです。

public class CustomerModel
{
    public virtual string Id { get; set; }
    public virtual string Name { get; set; }

    public virtual IList<PreferredAirportModel> PreferedAirports { get; set; }
}

public class AirportModel
{
    public virtual string Id { get; set; }
    public virtual string AirportName { get; set; }
}

public class PreferredAirportModel
{
    public virtual AirportModel Airport { get; set; }
    public virtual int CheckInMinutes { get; set; }
}

// ViewModels
public class CustomerViewModel
{
    [Required]
    public virtual string Id { get; set; }
    public virtual string Name { get; set; }

    public virtual IList<PreferredAirporViewtModel> PreferedAirports { get; set; }
}

public class PreferredAirporViewtModel
{
    [Required]
    public virtual string AirportId { get; set; }

    [Required]
    public virtual int CheckInMinutes { get; set; }
}

そして、これはエレガントなソリューションではないコントローラーです。

public class CustomerController
{
    public ActionResult Save(string id, CustomerViewModel viewModel)
    {
        var session = SessionFactory.CurrentSession;

        var customer = session.Query<CustomerModel>().SingleOrDefault(el => el.Id == id);

        customer.Name = viewModel.Name;

        // How can I Merge collections handling delete, update and inserts ?

        var modifiedPreferedAirports = new List<PreferredAirportModel>();
        var modifiedPreferedAirportsVm = new List<PreferredAirporViewtModel>();

        // Update every common Airport
        foreach (var airport in viewModel.PreferedAirports)
        {
            foreach (var custPa in customer.PreferedAirports)
            {
                if (custPa.Airport.Id == airport.AirportId)
                {
                    modifiedPreferedAirports.Add(custPa);
                    modifiedPreferedAirportsVm.Add(airport);

                    custPa.CheckInMinutes = airport.CheckInMinutes;
                }
            }
        }

        // Remove common airports from ViewModel
        modifiedPreferedAirportsVm.ForEach(el => viewModel.PreferedAirports.Remove(el));

        // Remove deleted airports from model
        var toDelete = customer.PreferedAirports.Except(modifiedPreferedAirports);
        toDelete.ForEach(el => customer.PreferedAirports.Remove(el));

        // Add new Airports
        var toAdd = viewModel.PreferedAirports.Select(el => new PreferredAirportModel
                                                            {
                                                                Airport =
                                                                            session.Query<AirportModel>().
                                                                            SingleOrDefault(a => a.Id == el.AirportId),
                                                                CheckInMinutes = el.CheckInMinutes
                                                             });
        toAdd.ForEach(el => customer.PreferedAirports.Add(el));

        session.Save(customer);

        return View();
    }
}

私の環境は ASP.NET MVC 4、nHibernate、Automapper、SQL Server です。

4

1 に答える 1

2

ええと、「エレガント」が単に「すべてをクリアして再作成しないでください」(テストされていない)の場合:

var airports = customer.PreferedAirports;
var viewModelAirports = viewModel.PreferredAirports;

foreach (var airport in airports) {
  //modify common airports
   var viewModelAirport = viewModelAirports.FirstOrDefault(m => m.AirportId == airport.AirportId);
   if (viewModelAirport != null) {
      airport.X = viewModelAirport.X;
      airport.Z = viewModelAirport.Z;
      //remove commonAirports from List
      viewModelAirports.Remove(viewModelAirport);
      continue;
   }
   //delete airports not present in ViewModel
   customer.PreferedAirports.Remove(airport);
}

//add new airports
foreach (var viewModelAirport in viewModelAirports) {
   customer.PreferedAirports.Add(new PreferredAirportModel {
             Airport = session.Query<AirportModel>().SingleOrDefault(a => a.Id == el.AirportId), 
             CheckInMinutes = el.CheckInMinutes
             });
}
session.Save(customer);
于 2012-06-29T13:15:05.423 に答える