1

ライブラリに単一の DbContext があり、エンティティとその構成が流暢な API に含まれています。

この同じコンテキストを 2 つの異なるプロジェクトで使用しています。1 つ目はテスト プロジェクトで、2 つ目は単純なコンソール アプリケーションです。

次のような関係の一部を含むクエリを実行します。

var vacancies = (from v in ctx.Vacancies
                              .Include("Categories")
                              .Include("Levels")
                              .Include("Contracts")
                              .Include("JobTypes"));

奇妙なことに、コンソール アプリケーションは完全に動作しますが、単体テストが突然間違ったテーブルを検索し始めます。

私がそれらを見ると、両方のアプリケーションが非常に異なるクエリを生成します。

私はEF5 atmを使用していますが、この問題の原因についての手がかりが1つもないまま、数日間これに固執しています。

編集:ポイントは、私は別のクエリを実行しないことです。また、コンテキストのみを持ち、実行時に確認した1つの接続文字列のみが適切なデータベースに接続します。

私が言えることは、流暢なAPIは、本来のようにコードにうまくヒットしても、ユニットテストでは効果がないように感じるということだけです。

 public class SchedulerContext : BaseContext<SchedulerContext>{


    public DbSet<Click> Clicks { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<ContractType> Contracts { get; set; }
    public DbSet<JobType> JobTypes { get; set; }
    public DbSet<Level> Levels { get; set; }
    public DbSet<ExternalMapping> ExternalMappings { get; set; }     
    public DbSet<GeoName> GeoNames { get; set; }
    public DbSet<GeoAlternateName> GeoAlternateNames { get; set; }     
    public DbSet<Trigger> JobTriggers { get; set; }
    public DbSet<RegistryValue> RegistryValues { get; set; }
    public DbSet<JobResult> JobResults { get; set; }
    public DbSet<JobInfo> JobInfo { get; set; }
    public DbSet<JobError> JobErrors { get; set; }
    public DbSet<JobNotification> JobNotifications { get; set; }
    public DbSet<Company> Customers { get; set; }
    public DbSet<Vacancy> Vacancies { get; set; }

    public SchedulerContext() {
        //this.Configuration.ProxyCreationEnabled = false;
        //this.Configuration.LazyLoadingEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {

        modelBuilder.Configurations.Add(new VacancyEntityTypeConfiguration());
        base.OnModelCreating(modelBuilder);
    }
}

それが私の文脈です。

そして私のエンティティ構成:

public class VacancyEntityTypeConfiguration : EntityTypeConfiguration<Vacancy> {

    public VacancyEntityTypeConfiguration() {
        this.HasMany(c => c.Levels).
       WithMany().
       Map(
        m => {
            m.ToTable("VacancyLevels");
        });

        this.HasMany(c => c.Categories).
          WithMany().
          Map(
           m => {
               m.ToTable("VacancyCategories");
           });

        this.HasMany(c => c.Contracts).
          WithMany().
          Map(
           m => {
               m.ToTable("VacancyContractTypes");
           });

        this.HasMany(c => c.Jobtypes).
          WithMany().
          Map(
           m => {
               m.ToTable("VacancyJobTypes");
           });
    }
}

そして、問題を示す正確な方法。

 public List<Vacancy> GetVacanciesForCustomer(Company customer, bool onlineInclusive) {
        using (var ctx = new JHSchedulerContext.SchedulerContext()) {
            var vacancies = (from v in ctx.Vacancies.Include("Categories").Include("Levels").Include("Contracts").Include("JobTypes") where v.SourceSite == customer.SourceSite && (v.Online || onlineInclusive == false) select v).ToList();
            return vacancies.ToList();
        }
    }

そして欠員クラス:

 public class Vacancy {

    public Vacancy()
    {
        this.Language = "";
    }

    [SolrUniqueKey("id")]
    [Key]
    [Required]
    public int Id { get; set; }

    [StringLength(50, ErrorMessage = "Maximum length 50 characters")]
    public string ExternalId { get; set; }

    [SolrField("title")]
    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string Title { get; set; }

    [SolrField("company")]
    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string Company { get; set; }

    [StringLength(4096, ErrorMessage = "Maximum length 4096 characters")]
    public string CompanyText { get; set; }

    [SolrField("location")]
    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string Location { get; set; }

    [SolrField("url")]
    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string Url { get; set;}

    [SolrField("source")]
    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string SourceSite { get; set; }

    private string text;
    [SolrField("text")]
    [StringLength(4096, ErrorMessage = "Maximum length 4096 characters")]
    public string Text {
        get {
            return StringHelper.TruncateAtWord(text, 500);
            //return new String(text.Take(500).ToArray());
            //return text.Substring(text.Length < 900 ? 0 : (text.Length / 2), (int)Math.Min(text.Length, 500));
        }
        set{
            text = value;
        }
    }

    [StringLength(4096, ErrorMessage = "Maximum length 4096 characters")]
    public string TextProfile { get; set; }

    [StringLength(4096, ErrorMessage = "Maximum length 4096 characters")]
    public string TextOffer { get; set; }

    [NotMapped]
    [ScriptIgnore]
    public SqlGeography Coordinate {
        get
        {
            if (Latitude.HasValue && Longitude.HasValue)
                return SqlGeography.Point(Latitude.Value, Longitude.Value, 4326);
            else
                return null;
        }
    }

    [SolrField("coordinate_0_coordinate")]
    public double? Latitude { get; set; }

    [SolrField("coordinate_1_coordinate")]
    public double? Longitude { get; set; }

    [StringLength(1024, ErrorMessage = "Maximum length 1024 characters")]
    public string NormalizedLocation { get; set; }

    public DateTime? ScrapedDate { get; set; }

    [SolrField("insertdate")]
    public DateTime? ImportDate { get; set; }

    public DateTime? ExpireDate { get; set; }     

    [NotMapped]
    public string DaysAgo {
        get {
            if (ImportDate != null)
                return (DateTime.Now - (DateTime)ImportDate).Days.ToString();
            else {
                return "N/A";
            }
        }
    }

    [SolrField("category")]
    public ICollection<string> CategoryNames {
        get { return Categories != null ? Categories.Select(c => c.Name).ToList() : null; }
    }

    [SolrField("level")]
    public ICollection<string> LevelNames {
        get { return Levels != null ? Levels.Select(l => l.Name).ToList() : null; }
    }

    [SolrField("contract")]
    public ICollection<string> ContractNames {
        get { return Contracts != null ? Contracts.Select(c => c.Name).ToList() : null; }
    }

    [SolrField("time")]
    public ICollection<string> JobTypeNames {
        get { return Jobtypes != null ? Jobtypes.Select(c => c.Name).ToList() : null; }
    }

    public string ContactName { get; set; }       

    [Required]
    public bool Online { get; set; }

    [NotMapped]
    public int? Distance { get; set; }

    public string Language { get; set; }

    public string PriorityType { get; set; }

    public int NumClicks { get; set; }

    [NotMapped]
    public string GridContactName {
        get{
            return string.Format("{0} (Total Clicks:{1})",ContactName,NumClicks);
        }
    }

    public virtual ICollection<Level> Levels { get; set; }

    public virtual ICollection<Category> Categories { get; set; }

    public virtual ICollection<ContractType> Contracts { get; set; }

    public virtual ICollection<JobType> Jobtypes { get; set; }     

    public override string ToString() {
        return string.Format("Id={0} ExternalId={1} Title={2} Company={3} Location={4} Url={5} SourceSite={6} Text={7} NormalizedLocation={8} InsertDate={9} ImportDate={10} DaysAgo={11}",Id, ExternalId,Title,Company,Location,Url, SourceSite,Text,NormalizedLocation,ScrapedDate,ImportDate,DaysAgo);
    }

}

そして Level クラス (他のすべての関係クラスは同じ構造 (name,id) を持っています:

   public class Level {

    [Key]
    [Required]
    public int Id { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "Maximum length 100 characters")]
    public string Name { get; set; }      

    public override string ToString() {
        return string.Format("Id={0} Name={1}", Id, Name);
    }

}

データベースへの接続に関する限り、両方が同じデータベースに接続していることを確認したことを信じてください.まだまったく同じ問題がありました)。

明確にするために:ユニットテストはテーブルを探します:CategoryVacancy。コンソール アプリケーションまたは Windows サービスでさえ、これを使用して正しいテーブルを探します: VacancyCategories.

4

0 に答える 0