2

가리키며 여러 속성 :EF 코드 첫째 - 내가 EF 4.1에서 코드 첫 번째에서 데이터베이스를 생성하는 간단한 한 쌍의 클래스가 또 다른 표

public class User 
{ 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
} 

public class Purchase 
{ 
    public int PurchaseId { get; set; } 
    public int UserId { get; set; } 
    public int? SalespersonUserId { get; set; } 

    public User User { get; set; } 
    public User SalespersonUser { get; set; } 
} 

public class NewItemsDataContext : DbContext 
{ 
    public DbSet<User> Users { get; set; } 
    public DbSet<Purchase> Purchases { get; set; } 
} 

내 프로그램에서, 나는 작성하고 일부 데이터를 작성합니다. 내가 다시 구매 기록을 읽을 때

class Program 
{ 
    static void Main(string[] args) 
    { 
     Database.SetInitializer<NewItemsDataContext>(new DropCreateDatabaseIfModelChanges<NewItemsDataContext>()); 

     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      sadc.Users.Add(new User()); 

      sadc.SaveChanges(); 
     } 
     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      sadc.Purchases.Add(new Purchase() { UserId = 1 }); 
      sadc.SaveChanges(); 
     } 
     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      var sql = sadc.Purchases.Include(p => p.User); 
      foreach (Purchase purchase in sql) 
       Console.WriteLine(purchase.User.UserId.ToString()); 
     } 
    } 
} 

참고, 나는 purchase.User되는 널 (null)의 예외가 - 즉, .Include은 사용자에 대한 아무 것도 가져 오지 않았다. 내 OnModelCreating에서 salespersonUser 탐색 속성을 무시하면 이제 (또는 그냥 주석) :

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Purchase>().Ignore(p => p.SalespersonUser); 

    base.OnModelCreating(modelBuilder); 
} 

코드가 작동하고, 사용자는 .Include에로드됩니다.

SalespersonUser 탐색 속성을 무시하면 예상대로 데이터베이스가 만들어집니다. Purchase 테이블에는 PurchaseId, UserId 및 SalespersonId가 있습니다. 하지만 일단 SalespersonUser 탐색 속성을 다시 추가하면 (무시하면 중지됨) 테이블에 User_UserId 및 SalespersonUser_UserId (원래 UserId 및 SalespersonUserId는 물론)라는 두 개의 키가 추가됩니다.

또한 생성 된 SQL은 문제가 발생한 위치를 명확하게 보여줍니다. 순자산 재산없이

:

{SELECT 
[Extent1].[PurchaseId] AS [PurchaseId], 
[Extent1].[UserId] AS [UserId], 
[Extent1].[SalespersonUserId] AS [SalespersonUserId], 
[Extent2].[UserId] AS [UserId1], 
[Extent2].[UserName] AS [UserName] 
FROM [Purchases] AS [Extent1] 
INNER JOIN [Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]} 

및 탐색 속성 :

{SELECT 
[Extent1].[PurchaseId] AS [PurchaseId], 
[Extent1].[UserId] AS [UserId], 
[Extent1].[SalespersonUserId] AS [SalespersonUserId], 
[Extent2].[UserId] AS [UserId1], 
[Extent2].[UserName] AS [UserName], 
[Extent1].[SalespersonUser_UserId] AS [SalespersonUser_UserId] 
FROM [Purchases] AS [Extent1] 
LEFT OUTER JOIN [Users] AS [Extent2] ON [Extent1].[User_UserId] = [Extent2].[UserId]} 

는 사용자 아이디를 가져옵니다,하지만 User_UserId 조인하는 방법을 공지하고, 왼쪽은 더 적게, 참여하지 않습니다. SalespersonUserId는 조인에서도 참조되지 않습니다. 레코드를 작성한 후 데이터베이스 내부에서 UserId는 설정되지만 User_UserID는 null입니다. 따라서 아무 것도 참여할 수 없으며 포함 된 사용자에 대해서는 null이 반환됩니다.

이것이 EF의 버그 인 것처럼 보일 수도 있지만 설계 이유가있을 수 있습니다. 그렇다면 누군가 나를 위해 그것을 정리할 수 있으며, 아마도 주위에 사용할 수있는 유창한 API를 설명 할 수 있을까요? 나는 내 nav 속성의 일부분이다.

+0

그냥 호기심 : 속성 Purchase.UserId 및 Purchase.SalesPersonUserId의 목적은 무엇인가? 구입 정보가 ID를 찾을 수있는 User 및 SalesPersonUser에 대한 참조를 가지고 있기 때문에 중복 정보가 아닙니까? 전에 설치를 보지 못했습니다 ... –

+1

이것은 EF Database First를 사용하여 데이터베이스에서 생성 된 클래스를 얻는 방법입니다. 3 계층 시스템, 서버 측 데이터베이스, 데이터베이스에서 생성 된 클래스를 소비 및 전달하는 웹 서비스, 웹 서비스를 사용하는 WPF 클라이언트가 있습니다. – user1689571

답변

2

EF는 네비게이션 속성에 문제가있어 - 여분의 FK가 생성되는 이유입니다.

시도 you'r 명시 적으로 FK는 재산 관계를 탐색하는 매핑, 그래서이 유창 매핑을 추가 :

 modelBuilder.Entity<Purchase>() 
      .HasOptional(p => p.SalespersonUser) 
      .WithMany() 
      .HasForeignKey(p => p.SalespersonUserId); 

     modelBuilder.Entity<Purchase>() 
      .HasRequired(p => p.User) 
      .WithMany() 
      .HasForeignKey(p => p.UserId); 
+0

예! 당신의 대답이 들어 왔을 때 마침내 똑같은 코드가 작동 했었습니다. 마침내 그것을 이해했다고 생각합니다. 고마워요! – user1689571

+0

"EF가 내비게이션 속성에 문제가 있습니다 ..."라고 말하면 버그입니까? – user1689571

+0

버그는 아니지만 발전기의 혼란 - 관습에 따라 파악할 수 없었기 때문에이를 정리해야했습니다. –