3 messaggi dal 18 aprile 2018
Salve a tutti, sto realizzando un applicazione MVC che permetta agli utenti registrati di prendere appuntamenti, per farlo ho creato una tabella Appointment e messa in relazione con AspnetUser ma dal controller non riesco a mandare l'id dell'utente.
Vi mostro il codice cosi da spiegarvi meglio.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace toilette.Models
{
    // È possibile aggiungere dati del profilo per l'utente aggiungendo altre proprietà alla classe ApplicationUser. Per altre informazioni, vedere https://go.microsoft.com/fwlink/?LinkID=317594.
    public class Appointment
    {
       
        public int AppointmentId { get; set; }
        public string text { get; set; }

       
        public virtual ApplicationUser ApplicationUser { get; set; }
    }

    public class ApplicationUser : IdentityUser
    {
        public virtual Appointment Appointment { get; set; }
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Tenere presente che il valore di authenticationType deve corrispondere a quello definito in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Aggiungere qui i reclami utente personalizzati
            return userIdentity;
        }
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
        public DbSet<Appointment> Appointments { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // one-to-zero or one relationship between ApplicationUser and Customer
            // UserId column in Customers table will be foreign key
            modelBuilder.Entity<ApplicationUser>()
                .HasOptional(m => m.Appointment)
                .WithRequired(m => m.ApplicationUser)
                .Map(p => p.MapKey("UserId"));
        }
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
}


Si crea la riga UserId nella tabella Appointment, se inserisco manualmente l'id dell'utente nel DB funziona e riesco nel nella visualizzazione e mostrare solo gli appuntmanti dell'utente registrato.
Ma dal controller Appointments non riesco a mandargli l'id utente in modo che questo possa creare l'appuntamento dalla visualizzazione.
(se provo dalla visualizzazione a creare l'appuntmanto mi ritorna questo errore:
Le entità in 'ApplicationDbContext.Appointments' fanno parte della relazione 'ApplicationUser_Appointment'. Trovati 'ApplicationUser_Appointment_Source' correlati a 0. Previsto 1 'ApplicationUser_Appointment_Source'.)
Grazie in anticipo per chi vorrà aiutarmi
10.600 messaggi dal 09 febbraio 2002
Contributi
Ciao,
ogni utente può avere avere molteplici appuntamenti? Se è questo il caso, dovresti sostituire HasOptional con HasMany. Al momento, infatti, stai creando una relazione uno a uno, mentre a te probabilmente serve uno a molti.


Trovati 'ApplicationUser_Appointment_Source' correlati a 0. Previsto 1 'ApplicationUser_Appointment_Source'.)

Se crei relazioni uno a uno, l'AppointmentId deve essere valorizzato con l'id dell'utente, non può essere un intero autoincrementante.


ciao,
Moreno

Enjoy learning and just keep making
3 messaggi dal 18 aprile 2018
Ciao Moreno, grazie della risposta, in realtà si ho bisogno di creare la relazione uno a molti..
Ho seguito molte guide ma non sono mai riuscito, come posso fare questa relazione?
Ho provato anche a lasciare la definizione cosi come era quindi con .HasOptional ma nulla non vado avanti.


public class Appuntamento
    {
        [Key]
        public int idAppuntamento { get; set; }
        
      //  public string UserId{ get; set; } // questo immagino dovrebbe essere la chiave di collegamento\

        public string Testo { get; set; }
        public int idServizio { get; set; }
        [ForeignKey("idServizio")]
        public Servizio servizi { get; set; }
        public DateTime Start_Data { get; set; }
        public DateTime End_Data { get; set; }
        
  public virtual ApplicationUser ApplicationUser { get; set; }
    }

    public class ApplicationUser : IdentityUser
    {
        public virtual Appuntamento Appuntamenti { get; set; }
     
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Tenere presente che il valore di authenticationType deve corrispondere a quello definito in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Aggiungere qui i reclami utente personalizzati
             
            return userIdentity;
        }
    }

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
        
        public DbSet<Appuntamento> Appuntamenti { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // one-to-zero or one relationship between ApplicationUser and Customer
            // UserId column in Customers table will be foreign key
            modelBuilder.Entity<ApplicationUser>()
                .HasMany(m => m.Appuntamenti) //segnalato come rosso
                .WithRequired(m => m.ApplicationUser)
                .Map(t=>t.MapKey("UserId"));

            

        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }

     
      
        
    }

Naturalmente ho lo stesso problema di prima non riuscendo a popolare l'UserId
Grazie mille per il tuo tempo
Modificato da Mirko2018 il 25 aprile 2018 00.19 -
Modificato da Mirko2018 il 25 aprile 2018 00.29 -
Modificato da Mirko2018 il 25 aprile 2018 02.01 -
10.600 messaggi dal 09 febbraio 2002
Contributi
Ciao, segui queste istruzioni per mappare la relazione uno a molti:

http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

Nella classe Appuntamento, prova a decommentare la proprietà UserId che giustamente hai messo. Poi, mappa così la relazione nel metodo OnModelCreating.
modelBuilder
  .Entity<Appuntamento>()
  .HasRequired(m => m.ApplicationUser)
  .WithMany()
  .HasForeignKey(a => a.UserId);


Vedi che in WithMany non ho indicato alcun parametro. Questo perché in ApplicationUser non hai creato una collezione Appointments, motivo per cui te lo segnava rosso. Comunque, non è obbligatorio creare la colluzione, e può andar bene così. La crei solo se hai bisogno di accedere agli appuntamenti di un utente partendo da un oggetto ApplicationUsers.

Nota: per mappare le relazioni dovresti usare o gli attributi o l'interfaccia fluente, per coerenza. Vedo invece che stai usando un mix: nella classe Appuntamento hai mappato la relazione con Servizio usando gli attributi, mentre invece la relazione con ApplicationUser l'hai mappata dal metodo OnModelCreating, usando l'interfaccia fluente.

ciao,
Moreno
Modificato da BrightSoul il 25 aprile 2018 09.37 -

Enjoy learning and just keep making
3 messaggi dal 18 aprile 2018
Diciamo che è ok ovvero il campo UserId in Appuntamenti è obbligatorio però mi hai dato un buon input e anche se mi ha creato anche nella cartella AspNetUsers una colonna che non mi serve sta funzionando lo stesso quindi diciamo che per il momento mi accontento e piano piano lo miglioro.

Approfitto della tua gentilezza, se posso chiedere sempre a te... ho inserito il fullcalendar va tutto bene ma ho un piccolo problema, mi spiego, nell'index ho gestito i dati tramite jquery in modo che appaia un modal quando si clicca sull'evento con i dati reltivi all'appuntamento.. il problema è che chiaramente mi viene mostrato l'id e non il nome dell'utente tra i dettagli, non sono riuscito a fare il join per averlo come risultato. Ti posto il codice:
Nell'index:

            function GenerateCalender(events) {
                $('#calender').fullCalendar('destroy');
                $('#calender').fullCalendar({
                    contentHeight: 400,
                    defaultDate: new Date(),
                    timeFormat: 'h(:mm)a',
                    header: {
                        left: 'prev,next today',
                        center: 'title',
                        right: 'month,basicWeek,basicDay,agenda'
                    },
                    eventLimit: true,
                    eventColor: '#378006',
                    events: events,
                    eventClick: function (calEvent, jsEvent, view) {
                        selectedEvent = calEvent;
                        $('#myModal #eventTitle').text(calEvent.title);
                        var $description = $('<div/>');
                        $description.append($('<p/>').html('<b>Start:</b>' + calEvent.start.format("DD-MMM-YYYY HH:mm a")));
                        if (calEvent.end != null) {
                            $description.append($('<p/>').html('<b>End:</b>' + calEvent.end.format("DD-MMM-YYYY HH:mm a")));
                        }

                        $description.append($('<p/>').html('<b>Description:</b>' + calEvent.description));
                        $description.append($('<p/>').html('<b>UserId:</b>' + calEvent.UserId));
                        
                        $('#myModal #pDetails').empty().html($description);

                        $('#myModal').modal();
                    },
                    selectable: true,
                    select: function (start, end) {
                        selectedEvent = {
                            eventID: 0,
                            title: '',
                            description: '',
                            start: start,
                            end: end,
                            allDay: false,
                            color: ''
                        };
                        openAddEditForm();
                        $('#calendar').fullCalendar('unselect');
                    },
                    editable: true,
                    eventDrop: function (event) {
                        var data = {
                            EventID: event.eventID,
                            Subject: event.title,
                            Start: event.start.format('DD/MM/YYYY HH:mm A'),
                            End: event.end != null ? event.end.format('DD/MM/YYYY HH:mm A') : null,
                            Description: event.description,
                            ThemeColor: event.color,
                            IsFullDay: event.allDay
                        };
                        SaveEvent(data);
                    }
                })
            }



Nel controller:

 public JsonResult GetEvents()
        {
            using (Entities dc = new Entities())
            {
                var events = dc.Events.ToList();
                return new JsonResult { Data = events, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
        }


qui mi restituisce la stringa con l'id e che dovrei convertire con il nome dell'utente:

                        $description.append($('<p/>').html('<b>UserId:</b>' + calEvent.UserId));



Grazie mille del tuo tempo.
10.600 messaggi dal 09 febbraio 2002
Contributi
Ciao,
non dovresti restituire al client le entità così come sono. Questo non andrebbe fatto...

using (Entities dc = new Entities())
{
var events = dc.Events.ToList();
return new JsonResult { Data = events, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}


Quindi dovresti crearti una nuova classe che puoi chiamare EventDto (o come vuoi tu) in cui metti soltanto le proprietà che servono al FullCalendar, tipo la data, il titolo e il nome dell'utente. Se non facessi così, rischieresti di divulgare al client più dati del necessario.

Quindi, devi operare una proiezione con il metodo Select che ti trasformerà l'entità Event nel tipo EventDto.

non sono riuscito a fare il join

Dimentica le join, quello è un concetto del mondo relazionale. Qui sei nel mondo concettuale e per ottenere i dati di entità correlate si usando le proprietà di navigazione.
Ti ricordi? Quando abbiamo mappato la relazione tra Appuntamento e Utente abbiamo indicato " .HasRequired(m => m.ApplicationUser)". Quella ApplicationUser è appunto la proprietà di navigazione che ti porta ad accedere ai dati dell'utente senza dover fare join esplicite.

Quindi, prova così. Vado a braccio quindi è probabile che il codice sia sbagliato. Cerca di carprirne l'intento.
using (Entities dc = new Entities())
{
  var events = dc.Events.
   Select(e => new EventDto {
      Id = e.Id,
      Title = e.Title,
      Username = e.ApplicationUser.Username,
      Date = e.Date
   }).ToList();
  return new JsonResult { Data = events, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}


EventDto sarà una nuova classe definita così:
public class EventDto {
  public int Id { get; set; }
  public string Title { get; set; }
  public string Username { get; set; }
  public DateTime Date { get; set; }
}


ciao,
Moreno

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.