0

유창한 API로 EF 코드의 첫 번째 방법을 사용하고 있습니다. 등록 신청서에 하나의 등록 양식이 있습니다. 등록 후보자에서 미리 정의 된 옵션 세트 (향후 증가 할 수 있지만 기회는 매우 드뭅니다)가있는 드롭 다운에서 여러 옵션을 선택할 수 있습니다 (등록 양식의 드롭 다운에 관심 있음). 사용자가 양식을 제출하면이 레코드를 데이터베이스에 저장하려고합니다. 그래서 다음과 같은 엔티티를 만들었습니다.다 대다 엔티티 프레임 워크 및 리포지토리 패턴 삽입/업데이트

등록과 후보자 정보를 얻을에서 관심에서 여러 옵션을 선택할 수 있습니다 사용자를 채 웁니다 가입 양식에 드롭 다운에서 어디에 관심에서

public class Participant 
    { 
     public Participant() 
     { 
      Interests = new Collection<Interest>(); 
     } 
     [Key, ForeignKey("User")] 
     public int Id { get; set; } 
     [DisplayName("First Name")] 
     [StringLength(50, ErrorMessage = "First name cannot be more than 50 characters")] 
     [Required(ErrorMessage = "You must fill in first name")] 
     public string FirstName { get; set; } 

     [DisplayName("Last Name")] 
     [StringLength(50, ErrorMessage = "Last name cannot be more than 50 characters")] 
     [Required(ErrorMessage = "You must fill in last name")] 
     public string LastName { get; set; } 

     [Required(ErrorMessage = "You must indicate your full birthday")] 
     [DisplayName("Birthday")] 
     [DataType(DataType.DateTime)] 
     public DateTime BirthDate { get; set; } 

     [DisplayName("Gender")] 
     [Required(ErrorMessage = "You must select gender")] 
     public int Gender { get; set; } 

     public string Address { get; set; } 

     public int CountryId { get; set; } 
     public Country Country { get; set; } 

     [DisplayName("Zip code")] 
     [StringLength(10, ErrorMessage = "Zip code cannot be more than 10 characters")] 
     public string ZipCode { get; set; } 

     public string Mobile { get; set; } 

     public string PhotoUrl { get; set; } 

     public virtual User User { get; set; } 

     public virtual ICollection<Interest> Interests { get; set; } 

     public string MedicalConditions { get; set; } 
} 

관심 클래스 저장됩니다 참가자 클래스 드롭 다운

이자 클래스

public class Interest 
    { 
     public Interest() 
     { 
      Participants = new Collection<Participant>(); 
     } 
     public int Id { get; set; } 
     public string InterestName { get; set; } 
     public virtual ICollection<Participant> Participants { get; private set; } 
    } 

각 참가자의 관심을 유지하기 위해 다음 스키마가있는 DB에 ParticipantInterests 테이블을 만들었습니다. ParticipantInterests Id (PK) ParticipantId (참가자 테이블의 FK) InterestId (FK Interests 테이블)

public virtual ICollection Participants {get; 세트; } 관심 모델 및

public virtual ICollection Interests {get; 세트; } 참여자 모델에서 다 대 다 연관을 형성합니다.

public class STNDataContext : DbContext 
    { 
     public DbSet<Participant> Participants { get; set; } 
     public DbSet<User> Users { get; set; } 
     public DbSet<Country> Countries { get; set; } 
     public DbSet<Interest> Interests { get; set; } 
     public DbSet<Role> Roles { get; set; } 
     public DbSet<SecurityQuestion> SecurityQuestions { get; set; } 

     public DbSet<Tour> Tours { get; set; } 
     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<Participant>() 
       .HasKey(p => p.Id); 

      modelBuilder.Entity<User>() 
       .HasOptional(u => u.Participant) 
       .WithRequired(); 

      modelBuilder.Entity<Participant>() 
      .HasMany(p => p.Interests) 
      .WithMany(i => i.Participants) 
      .Map(m => 
      { 
       m.ToTable("ParticipantInterests"); 
       m.MapLeftKey("ParticipantId"); 
       m.MapRightKey("InterestId"); 
      }); 

      modelBuilder.Entity<User>().HasRequired(u => u.Role); 
      modelBuilder.Entity<Participant>().HasRequired(p => p.Country); 
      modelBuilder.Entity<User>().HasOptional(u => u.SecurityQuestion); 
     } 


     public virtual void Commit() 
     { 
      base.SaveChanges(); 
     } 

컨트롤러 액션 코드

public virtual ActionResult Register(StudentRegisterViewModel studentRegisterViewModel) 
     { 
      if (ModelState.IsValid) 
      { 
       if (_userService.IsUserExists(studentRegisterViewModel.Participant.User) == false) 
       { 
        studentRegisterViewModel.Participant.User.Username = studentRegisterViewModel.Username; 
        studentRegisterViewModel.Participant.User.Email = studentRegisterViewModel.Email; 
        studentRegisterViewModel.Participant.User.DateCreated = DateTime.Now; 
        studentRegisterViewModel.Participant.User.Id = 3; 
        studentRegisterViewModel.Participant.User.IsApproved = false; 
        studentRegisterViewModel.Participant.User.RoleId = 2; 
        studentRegisterViewModel.Participant.CountryId = 1; 
        var interests = new List<Interest>(); 
        foreach (var interestItem in studentRegisterViewModel.SelectedInterests) 
        { 
         var interest = new Interest { Id = interestItem }; 
         interest.Participants.Add(studentRegisterViewModel.Participant); 
         interests.Add(interest); 
         studentRegisterViewModel.Participant.Interests.Add(interest); 
        } 
        studentRegisterViewModel.Participant.Interests = interests; 
        _participantService.CreatParticipant(studentRegisterViewModel.Participant); 
        var user = _userService.GetUser(studentRegisterViewModel.Participant.User.Username); 
       } 
      } 
      studentRegisterViewModel.Gender = 
       Enum.GetNames(typeof(Gender)).Select(
        x => new KeyValuePair<string, string>(x, x.ToString(CultureInfo.InvariantCulture))); 
      studentRegisterViewModel.Interests = _interestService.GetAllInterests(); 
      return View(studentRegisterViewModel); 
     } 

참가자 저장소 (DAL)

public class ParticipantRepository : Repository<Participant>, IParticipantRepository 
    { 
     public ParticipantRepository(IDatabaseFactory databaseFactory) 
      : base(databaseFactory) 
     { 
     } 
    } 

참가자 서비스를 다음과 같이 내 데이터 컨텍스트 클래스는 (BLL) 워크 클래스

public class UniOfWork : IUnitOfWork 
{ 
    private readonly IDatabaseFactory _databaseFactory; 
    private STNDataContext _stnDataContext; 

    public UniOfWork(IDatabaseFactory databaseFactory) 
    { 
     this._databaseFactory = databaseFactory; 
    } 

    public STNDataContext StnDataContext 
    { 
     get { return _stnDataContext ?? (_stnDataContext = _databaseFactory.Get()); } 
    } 

    public void Commit() 
    { 
     StnDataContext.Commit(); 
    } 

} 

public class ParticipantService : IParticipantService 
    { 
     private readonly IParticipantRepository _participantRepository; 
     private readonly IUnitOfWork _unitOfWork; 

     public ParticipantService(IParticipantRepository participantRepository, IUnitOfWork unitOfWork) 
     { 
      this._participantRepository = participantRepository; 
      this._unitOfWork = unitOfWork; 
     } 

     public void CreatParticipant(Participant participant) 
     { 
      _participantRepository.Add(participant); 
      _unitOfWork.Commit(); 
     } 
} 

데이터베이스 공장

public class DatabaseFactory : Disposable, IDatabaseFactory 
    { 
     private STNDataContext _stnDataContext; 
     public DatabaseFactory() 
     { 
      Database.SetInitializer<STNDataContext>(null); 
     } 
     public STNDataContext Get() 
     { 
      return _stnDataContext ?? (_stnDataContext = new STNDataContext()); 
     } 
     protected override void DisposeCore() 
     { 
      if (_stnDataContext != null) 
       _stnDataContext.Dispose(); 
     } 
    } 

단위는 내가 오류를 다음 얻을 참가자를 만들려고 할 때.

'InterestName'열, 'StudyTourNetworkDB.dbo.Interests'테이블에 NULL 값을 삽입 할 수 없습니다. 열이 널을 허용하지 않습니다. INSERT가 실패합니다. \ r \ n 명령문이 종료되었습니다.

이상적으로는 참가자 정보를 Participants 테이블에, Participants Interests in ParticipantsInterests 테이블에 삽입해야합니다. 그러나 그것은 일어나서는 안되는 Interests 테이블에 레코드를 삽입하려고합니다.이 문제를 해결하도록 도와주세요. 나는 many-to-many 연관을 만들어 잘못을 저지를 수도있다.

감사

참고 : 컬렉션 컨텍스트에 연결하지만이 작품의 저장소 패턴 및 장치와 같은 컨텍스트에 관심 모음을 추가하는 방법을 찾을 수 없습니다/추가되지 않습니다 관심 분야로 나는이 문제를 이해할 수 .

제게 해결책을 제공해주십시오. 미리 감사드립니다.

+0

코드를 필수 최소값으로 줄이십시오. 당신은 문제가 텍스트 벽에 빠져 있습니다. –

답변

0

모델에 포함 된 사본이 EF에 의해 추적되지 않아서 새 것으로 생각하기 때문에 Interest 객체가 다시 추가된다는 점이 맞습니다. 대신 리포지토리에서 버전을 찾아보고 추가해야합니다.

대신에 :

var interests = new List<Interest>(); 
foreach (var interestItem in studentRegisterViewModel.SelectedInterests) 
{ 
    var interest = new Interest { Id = interestItem }; 
    interest.Participants.Add(studentRegisterViewModel.Participant); 
    interests.Add(interest); 
    studentRegisterViewModel.Participant.Interests.Add(interest); 
} 
studentRegisterViewModel.Participant.Interests = interests; 

것은 같은 것을 시도하십시오, 당신은 양쪽을 설정하는 다 대다 관계 필요가 없습니다에 있음을

// Look up the actual EF entities which match your selected items. You'll 
// probably need to adapt this to make it work 
var selectedInterestIds = studentRegisterViewModel.SelectedInterests.Select(i => i.Id); 
var interests = _interestService.GetAllInterests().Where(i => selectedInterestIds.Contains(i.Id));  
studentRegisterViewModel.Participant.Interests = interests; 

주 - 당신의 예제에서 당신 Interest 엔티티의 Participant 필드를 채우고있었습니다 - 참가자의 Interests 속성에 추가하기 때문에 EF가 자동으로 설정합니다.

+0

안녕하세요. 빠른 답변 주셔서 감사합니다. – pbhalchandra

+0

이제이 오류가 발생합니다. 엔티티 객체는 IEntityChangeTracker의 여러 인스턴스에 의해 참조 될 수 없습니다. – pbhalchandra

+0

안녕하세요 Richard의 대답에 감사드립니다. 당신의 솔루션은 작동하지만, 현재이 에러를 내고 있습니다. 엔티티 객체는 IEntityChangeTracker의 다중 인스턴스에 의해 참조 될 수 없습니다. 이것을위한 어떤 해결책. 다시 한 번 감사드립니다 – pbhalchandra

관련 문제