7

SQL Server 2012 데이터베이스에 대해 DbContext POCO 방식을 사용하여 Entity Framework 4.3.1을 사용하고 있습니다.datetime에서 탐색 속성이로드되지 않는 이유는 무엇입니까?

나는 데이터베이스에있는 두 테이블을 가지고 있고는 다음과 같습니다 :

tables

참고 : 모든 데이터베이스에 지정된 외부 키가 없습니다 - I 만의 관계를 시행하고있다가 모델 (나는 데이터베이스를 변경할 수 없다).

그들은 각각 다음과 같습니다 그들에 하나 개의 데이터 행이 : 이제

validation

:

data

는 내가 일하는 것이 참여를 보장하기 위해 다음 쿼리를 수행 , 다음 단체가 있습니다 :

public class Two 
{ 
    public long TwoId { get; set; } 
    public string OneId { get; set; } 
    public virtual One One { get; set; } 
} 

public class One 
{ 
    public string OneId { get; set; } 
    public DateTime DeliveryDate { get; set; } 
    public virtual ICollection<Two> Twos { get; private set; } 

    public void AddTwo(Two two) 
    { 
     if (two == null) 
      throw new ArgumentNullException("two"); 

     if (Twos == null) 
      Twos = new List<Two>(); 

     if (!Twos.Contains(two)) 
      Twos.Add(two); 

     two.One = this; 
    } 
} 

그리고 이것은 환경을 말한다 : 나는 내 콘솔에 인쇄 Why is this printed?를 얻을 코드의이 비트 실행하면

public class TestContext : DbContext 
{ 
    public TestContext(string conectionString) 
     : base(conectionString) 
    { 
     Configuration.LazyLoadingEnabled = true; 
     Ones = Set<One>(); 
     Twos = Set<Two>(); 
    } 
    public DbSet<One> Ones { get; private set; } 
    public DbSet<Two> Twos { get; private set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     var one = modelBuilder.Entity<One>(); 
     one.ToTable("One"); 
     one.HasKey(d => d.OneId); 

     var two = modelBuilder.Entity<Two>(); 
     two.ToTable("Two"); 
     two.HasKey(d => new 
          { 
           d.OneId, 
           d.TwoId 
          }); 
     two.Property(p => p.TwoId) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
     two.HasRequired(t => t.One) 
      .WithMany(o => o.Twos) 
      .HasForeignKey(o => o.OneId); 
     base.OnModelCreating(modelBuilder); 
    } 
} 

- 당신이 탐색 속성 (I 채워되어야한다고 볼 수 있듯이 내가 기대하지 않습니다 심지어 명시 적으로)을 포함 :

using (var ctx = new TestContext(@"......")) 
{ 
    const string oneId = "111348718"; 
    var one = ctx.Ones.Single(o => o.OneId.Equals(oneId)); 

    if (one != null) 
    { 
     var sdi = ctx 
      .Twos 
      .Include(s => s.One) 
      .Single(s => s.OneId.Equals(oneId)); 

     if (sdi.One == null) 
     { 
      Console.WriteLine("Why is this printed?"); 
     } 
     else 
     { 
      Console.WriteLine("This is what I expect"); 
     } 
    } 
} 

이제 이가 정말 이상한 비트이 : 나는 단순히 잘 작동 One 클래스에서 DeliveryDate 속성을 주석 처리하면 (나는 This is what I expect 인쇄 t를 얻을 수 콘솔).

여기에 무슨 문제가 있으며 어떻게 해결할 수 있습니까?

참고 : 나는 올바르게 기대 값으로 설정되어있는 one 변수에 DeliveryDate 특성을 보면 날짜가 데이터베이스에서 확인을해야하며, 엔티티 프레임 워크를 완벽하게 실현 할 수 있도록.

추가 정보 :이 날짜는 중요하지 않습니다라는 사실 - 어떤 단순한 프로퍼티가 떨어지 전체를 일으키는 것 - -이 경우, 여전히 실패한 NVARCHAR 말이에 버그 같은 느낌 나 ...

답변

2

좋아요, 그래서 이것의 바닥에있어 이것이 Entity Framework의 버그라고 생각하지만 주위를 해결할 수 있습니다. 다음은 그게 무엇입니까 ...

두 테이블의 OneId 열 끝에 하나의 공백이 있습니다.

예 - 가면 그림 - 얼마나 끔찍한 고약한가!?

그래서 데이터베이스의 모든 nvarchar 열에 LTRIM(RTRIM(을 수행 한 sql 스크립트가 작성되었으며 모두 잘 작동합니다.

주어진 SQL 서버는 공백을 신경 쓰지 않습니다. (질문에서 조인 된 쿼리로 입증 됨) 엔티티 프레임 워크가 신경 써야한다는 점이 마음에 들지 않습니다. 특히 여기에서는 완전히 이상하고 일관성이 없습니다. 확실히 Single을 호출하여 sdi 변수가 채워지는 지점이 던져 졌거나 탐색 속성이 채워져 있어야합니다 - 하나 또는 다른 것이지만이 동작은 실제로 혼란 스럽습니다 (제 의견으로는) - 어떤 임의의 속성이있는 것은 무엇입니까? 물고기의 가격과 더불어?

여기에 완전성을 위해이 사실을 매우 간단하게 재현 할 무언가가 있습니다. 새 데이터베이스를 작성하고 다음에이 SQL 스크립트를 실행

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[One](
    [OneId] [nvarchar](10) NOT NULL, 
    [SomeInt] [int] NOT NULL, 
CONSTRAINT [PK_Delivery] PRIMARY KEY CLUSTERED 
(
    [OneId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

CREATE TABLE [dbo].[Two](
    [TwoId] [int] NOT NULL, 
    [OneId] [nvarchar](10) NOT NULL, 
CONSTRAINT [PK_DeliveryItem] PRIMARY KEY CLUSTERED 
(
    [TwoId] ASC, 
    [OneId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

INSERT INTO Two(TwoId, OneId) VALUES (1, '1 ') 
INSERT INTO One(OneId, SomeInt) VALUES ('1', 1.0) 

지금 교류 # 콘솔 응용 프로그램을 만듭니다의 EntityFramework (버전 4.3.1)과 System.Data.Entity에 대한 참조를 추가 이 코드를 넣고 실행하면 SHOULD NOT BE PRINTED!!!이 인쇄됩니다.

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Data.Entity; 
using System.Linq; 

namespace EFTest 
{ 
    public class Two 
    { 
     public int TwoId { get; set; } 
     public string OneId { get; set; } 
     public virtual One One { get; set; } 
    } 

    public class One 
    { 
     public string OneId { get; set; } 
     public virtual ICollection<Two> Twos { get; private set; } 

     // Comment out this property and it will work 
     public int SomeInt { get; set; } 

     public void AddTwo(Two two) 
     { 
      if (two == null) 
       throw new ArgumentNullException("two"); 

      if (Twos == null) 
       Twos = new List<Two>(); 

      if (!Twos.Contains(two)) 
       Twos.Add(two); 

      two.One = this; 
     } 
    } 

    public class Context : DbContext 
    { 
     public Context(string connectionString) 
      : base(connectionString) 
     { 
      Configuration.LazyLoadingEnabled = true; 
      Ones = Set<One>(); 
      Twos = Set<Two>(); 
     } 

     public DbSet<One> Ones { get; private set; } 
     public DbSet<Two> Twos { get; private set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder 
       .Entity<One>() 
       .HasKey(d => d.OneId) 
       .ToTable("One"); 

      var two = modelBuilder.Entity<Two>(); 
      two.ToTable("Two"); 
      two.HasKey(d => new 
           { 
            d.OneId, 
            d.TwoId 
           }); 

      two.Property(d => d.TwoId) 
       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

      two.HasRequired(m => m.One) 
       .WithMany(t => t.Twos) 
       .HasForeignKey(d => d.OneId); 

      base.OnModelCreating(modelBuilder); 
     } 
    } 

    internal class Program 
    { 
     private static void Main() 
     { 
      using (var ctx = new Context(@"your connection string")) 
      { 
       const string oneId = "1"; 
       var one = ctx.Ones.Single(o => o.OneId.Equals(oneId)); 

       if (one == null) 
       { 
        Console.WriteLine("No row with one ID in the database"); 
        return; 
       } 

       var two = ctx 
        .Twos 
        .Include(s => s.One) 
        .Single(s => s.OneId.Equals(oneId)); 

       Console.WriteLine(two.One == null 
             ? "SHOULD NOT BE PRINTED!!!" 
             : "SHOULD BE PRINTED"); 
      } 
     } 
    } 
} 

는 이들 중 하나를 수행합니다

  • 코멘트를 밖으로 SomeInt 특성을 One 클래스
  • 데이터베이스 (UPDATE Two SET OneId = RTRIM(OneId))의 공간을 트림에.

어느 쪽이든 작동합니다 (트리밍 만이 유일한 현실적인 수정입니다).