Domanda

Ci sono tonnellate di informazioni su questo, ma anche dopo aver letto per ore e ore non riesco a farlo funzionare nel modo desiderato.

Sto cercando di aggiornare un oggetto d'uso passando in un oggetto d'uso e genericamente confrontando le modifiche a un oggetto User tiro fuori del database. Finisco sempre per ottenere il NotSupportedException quando si utilizza questo metodo:

Un tentativo è stato fatto allegare o Aggiungere un ente che non è nuovo, forse imbarcati da un'altra DataContext. Questo non è supportato.

Ecco come sto provando a farlo:

    public void SaveUser(User User)
    {
        using (DataContext dataContext = new DataContext(WebConfigurationManager.ConnectionStrings["database"].ConnectionString))
        {
            // New user
            if (User.UserID == 0)
            {
                dataContext.Users.InsertOnSubmit(User);
            }
            // Existing user
            else
            {
                User dbUser = dataContext.Users.Single(u => u.UserID.Equals(User.UserID));
                Type t = dbUser.GetType();
                foreach (PropertyInfo p in t.GetProperties())
                {
                    if (p.CanWrite & p.GetValue(dbUser, null) != p.GetValue(User, null))
                    {
                        p.SetValue(dbUser, p.GetValue(User, null), null);
                    }
                }
                //dataContext.Refresh(RefreshMode.KeepCurrentValues, dbUser);
            }
            dataContext.SubmitChanges();
        }
    }

La linea commentata ho provato non è commentato anche, ma è stato di alcun aiuto.

Se io commento del ciclo foreach () e aggiungi una linea come dbUser.UserName = "Cheese"; esso aggiornerà il nome dell'utente nel bel database. Che mi porta a credere che sia qualcosa di come il ciclo foreach () modifica l'oggetto dbUser che causa questo di sicuro.

Quando il debug l'oggetto dbUser, sembra acquisire correttamente tutte le modifiche dall'oggetto utente che è stato passato come argomento.

Ho anche fatto qualche lettura sulla concorrenza ottimistica e aggiunto una colonna alla tabella del tipo di dati timestamp, ma che non sembra avere alcun effetto sia.

Che cosa sto facendo male qui?

Come posso ottenere questo per rilevare genericamente che cosa è cambiato e persistono correttamente le modifiche al database?

È stato utile?

Soluzione

La mia ipotesi è che c'è una relazione chiave esterna che si sta tentando di copiare che non è stato inizialmente caricato (a causa del lazy-carico) Durante la copia, si sta tentando di caricarlo, ma il DataContext è già stato eliminato.

ho lavorato su un problema simile. Ho finito per usare automapper per gestire la copia delle proprietà per me. Ho configurato automapper di ignorare il campo chiave primaria, nonché eventuali relazioni. Qualcosa di simile:

public void Update(User user)
{
     using (var db = new DataContext(...))
     {
         var userFromDb = db.Users.Where(x => x.Id == user.Id).Single();
         AutoMapper.Mapper.Map(user, userFromDb);
         db.SubmitChanges();
    }
}

La mia configurazione automapper è qualcosa di simile

AutoMapper.Mapper.Create<User, User>().ForMember(dest => dest.Id, opt => opt.Ignore())
                                      .ForMember(dest => dest.SomeRelation, opt => opt.Ignore());

Si possono trovare automapper qui: http://automapper.codeplex.com/

Altri suggerimenti

I mantenere il mio repo abbastanza magra, è solo compito è quello di interagire con il database. Costruisco un livello di servizio sulla parte superiore del pronti contro termine che fa un po 'di lavoro

public class EventRepository : IEventRepository
{

    private DBDataContext dc;
    public EventRepository()
    {
        dc = new DBDataContext();
    }

    public void Create(Event @event)
    {
        dc.Events.InsertOnSubmit(@event);
    }

    public System.Linq.IQueryable<Event> Read()
    {
        object events = (from e in dc.Eventse);
        return events.AsQueryable;
    }

    public void SubmitChanges()
    {
        dc.SubmitChanges();
    }

}

Poi la chiamata corrispondente dagli sguardi livello di servizio come questo

public void AddEvent(Event @event)
{
    _EventRepository.Create(@event);
}

public void SubmitChanges()
{
    _EventRepository.SubmitChanges();
}

E io lo chiamo dal mio controllo.

// AutoMapper will allow us to map the ViewModel with the DomainModel
Mapper.CreateMap<Domain.ViewModels.EventsAddViewModel, Domain.Event>();
object @event = Mapper.Map<Domain.ViewModels.EventsAddViewModel, Domain.Event>(eventToAdd);

// Add the event to the database
EventService.AddEvent(@event);
EventService.SubmitChanges();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top