1

I am trying to do unit testing on some classes that reply on an Entity Framework DB Context. For help, I managed to find a library called Effort, which seems to be a little old, and not very well documented, but it seems to work, and seems to be quite popular.

I am trying to use a CSV data loader.

When doing a ToArray() I receive an exceptions saying Sequence contains no matching element.

Any ideas on what I might be doing incorrectly? Or if not a different library I might want to give a chance?

A few snippets:

[Table("SEC_USER")]
public class SecUser {
    [Key][Column("USERID")]
    public int UserId { get; set; }

    [Column("USERNAME")]
    public string UserName { get; set; }
}

DB Context:

public class MusketeerDbContext : DbContext
{
    public virtual IDbSet<IbsCommunity> Communities { get; set; }
    public virtual IDbSet<IbsFunctionLinkLocation> Functionlinklocations { get; set; }
    public virtual IDbSet<IbsInstance> Instances { get; set; }
    public virtual IDbSet<SecUser> Users { get; set; }
    public virtual IDbSet<IbsFieldType> FieldTypes { get; set; }
    public virtual IDbSet<IbsLink> Links { get; set; }
    public virtual IDbSet<IbsFieldFll> FieldFlls { get; set; }
    public virtual IDbSet<IbsFieldValue> FieldValues { get; set; }

    public MusketeerDbContext() : base("name=EGS.My.MySettings.Conn") { }
    public MusketeerDbContext(DbConnection connection) : base(connection, true) { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("SA");
        modelBuilder.Conventions.Add(new FunctionConvention(typeof(OracleFunctions)));

        modelBuilder.Entity<IbsFieldValue>()
            .HasMany(fv => fv.InstancesFieldValues)
            .WithMany(i => i.InstancesFieldValues)
            .Map(mm =>
            {
                mm.MapLeftKey("FIELDVALUEID");
                mm.MapRightKey("INSTANCEID");
                mm.ToTable("IBS_INSTANCEFIELDVALUE");
            });
    }
}

public static class OracleFunctions
{
    [Function(FunctionType.BuiltInFunction, "TO_CHAR")]
    public static string ToChar(this int value) => Function.CallNotSupported<string>();

    [Function(FunctionType.BuiltInFunction, "TO_NCHAR")]
    public static string ToChar(this string value) => Function.CallNotSupported<string>();
}

The SEC_USER.csv:

USERID,USERNAME
"1","Jonathan"

The Test:

var path = @"C:\...\CSVs";
var dataLoader = new Effort.DataLoaders.CsvDataLoader(path);
var context = Effort.DbConnectionFactory.CreateTransient(dataLoader);
db = new MusketeerDbContext(context);
var users = db.Users.ToArray();

System.InvalidOperationException:

Message: "Sequence contains no matching element"
InnerException: null
StackTrace:
    at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
    at System.Data.Entity.Utilities.DbProviderManifestExtensions.GetStoreTypeFromName(DbProviderManifest providerManifest, String name)
    at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.ConfigureColumn(EdmProperty column, EntityType table, DbProviderManifest providerManifest)
    at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.Configure(EdmProperty column, EntityType table, DbProviderManifest providerManifest, Boolean allowOverride, Boolean fillFromExistingConfiguration)
    at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.<>c__DisplayClass4.<Configure>b__3(Tuple`2 pm)
    at System.Data.Entity.Utilities.IEnumerableExtensions.Each[T](IEnumerable`1 ts, Action`1 action)
    at System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive.PrimitivePropertyConfiguration.Configure(IEnumerable`1 propertyMappings, DbProviderManifest providerManifest, Boolean allowOverride, Boolean fillFromExistingConfiguration)
    at System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.ConfigurePropertyMappings(IList`1 propertyMappings, DbProviderManifest providerManifest, Boolean allowOverride)
    at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigurePropertyMappings(DbDatabaseMapping databaseMapping, EntityType entityType, DbProviderManifest providerManifest, Boolean allowOverride)
    at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EntityType entityType, DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
    at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntityTypes(DbDatabaseMapping databaseMapping, ICollection`1 entitySets, DbProviderManifest providerManifest)
    at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
    at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
    at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
    at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
    at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
    at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
    at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
    at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
    at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()
    at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
    at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
    at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
    at Igs.Musketeer.DbRepository.Tests.SecurityRepositoryTest..ctor() in C:\Users\me\Source\Repos\Musketeer\Igs.Musketeer.DbRepositoryTests\SecurityRepositoryTest.cs:line 21
JonathanPeel
  • 743
  • 1
  • 7
  • 19
  • Could you post the exception stack trace here? I suspect that the exception is thrown in a framework method. – Jean Hominal May 10 '17 at 13:31
  • Stack trace added. – JonathanPeel May 10 '17 at 13:38
  • The issue seems to be in the way that the `MusketeerDbContext` is configured, could you post the definition of that class? – Jean Hominal May 10 '17 at 14:31
  • 1
    For the sake of correctness this is not an unit test but an integration test. A unit test only uses data in memory, no files, no network, no db. – Ignacio Soler Garcia May 10 '17 at 14:38
  • I have added it. If I comment out OnModelCreating, I still have the same problems. Also, it does work, the only problem I am having is with unit testing. – JonathanPeel May 10 '17 at 14:39
  • @IgnacioSolerGarcia, what if I compiled the CSV as an embedded resource, and then loaded them? – JonathanPeel May 10 '17 at 14:40
  • Looks the same tome, to be an Unit Test you need to inject a Mock that has a predefined behavior (it returns always the same fixed constant data) instead of accessing a file. Unit Test should be fast, safe and repeatable. Just to let you know, it is not related directly with your issue. – Ignacio Soler Garcia May 10 '17 at 14:52
  • Thank you. And I know I can inherit by dbcontext, which if I don't come right with this soon, I might. I was looking for something "easy". – JonathanPeel May 10 '17 at 14:56

1 Answers1

3

I've just had this issue and I discovered the problem was that I was using the ColumnType data annotation. Even when I changed to using the model builder convention of HasColumnType, I still got the exact same error. I'm guessing one of your entities has that data annotation (or convention)?

If that's the case, the simplest fix would be to remove the data annotation. If not possible, I created a virtual property (e.g. public virtual bool IsInMemoryContext { get; } = false;) on the DbContext that I overrode in my tests - public override bool IsInMemoryContext { get; } = true;, and in the OnModelCreating method, I checked if this property was set, before adding the column types.

if (!IsInMemoryContext)
{
    modelBuilder.Entity<AuditLog>()
        .Property(e => e.EventType)
        .HasColumnType("char");
}

More information on the error can be found here: GitHub issue with Effort

Balah
  • 2,530
  • 2
  • 16
  • 24