9 votes

Base de données fantaisie Entity Framework

J'utilise Entity Framework 4+.

Est-il possible de créer automatiquement une base de données MOCK à partir du schéma avec des données aléatoires ? Où des ints, mettez des ints, où des chaînes, mettez des GUIDs ou autre...

Cela m'aiderait beaucoup à déboguer mon application.

Merci, James

2voto

NightOwl888 Points 4622

J'ai découvert cet outil formidable à utiliser avec EF 4 pour simuler la base de données. Il s'agit en fait d'un modèle T4 qui crée à la fois la couche EF "normale" et un objet fantaisie et une interface qui peuvent être utilisés pour les tests. Plus de documentation aquí .

Une mise en garde, cependant. En l'état, cela n'a pas fonctionné pour moi car le code de mon référentiel appelle SaveChanges() et d'autres méthodes qui ne sont pas implémentées dans l'interface générée. J'ai pu contourner ce problème en extrayant l'interface de l'implémentation ObjectContext de Microsoft et en créant ma propre interface IObjectContext. J'ai ensuite créé une classe de base (pour l'objet fantaisie) qui implémente cette interface en déléguant simplement chacun des appels à un objet fantaisie injecté. De cette façon, je peux utiliser Moq pour créer cette pièce dans ma classe de test, tout en conservant la possibilité de suivre les insertions, les mises à jour et les suppressions dans le simulateur généré.

Voici les modifications que j'ai apportées au modèle T4 "Contexte" pour résoudre ce problème. Désolé de faire ça par petits bouts - SO ne m'a pas laissé poster la liste complète du code parce qu'elle était trop longue.

Ajoutez ce code avant fileManager.Process();

fileManager.StartNewFile( "IObjectContext.cs");
WriteHeader();
WriteHeaderIncludeSystem();
WriteHeaderIncludeData();
WriteHeaderIncludeContainers();
WriteNamespaceBegin( code, namespaceName );
WriteObjectContextInterface( container, code );
WriteNamespaceEnd( namespaceName );

fileManager.StartNewFile( container.Name + "Mock.ObjectContext.cs");
WriteHeader();
WriteHeaderIncludeSystem();
WriteHeaderIncludeData();
WriteHeaderIncludeContainers();
WriteNamespaceBegin( code, namespaceName );
WriteObjectContextMockBase( container, code );
WriteNamespaceEnd( namespaceName );

Ajoutez ce code après le WriteInterface() bloc.

<#+
void WriteObjectContextInterface( EntityContainer container, CodeGenerationTools code )
{
#>
/// <summary>
/// The interface for the generic object context. This contains all of
/// the <code>ObjectContext</code> properties that are implemented in the 
/// concrete ObjectContext class. This interface was created so these members
/// can be mocked, as ObjectContext doesn't have a default public constructor.
/// </summary>
<#=Accessibility.ForType(container)#> interface IObjectContext : IDisposable
{
    void AcceptAllChanges();
    void AddObject(string entitySetName, object entity);
    TEntity ApplyCurrentValues<TEntity>(string entitySetName, TEntity currentEntity) where TEntity : class;
    TEntity ApplyOriginalValues<TEntity>(string entitySetName, TEntity originalEntity) where TEntity : class;
    void ApplyPropertyChanges(string entitySetName, object changed);
    void Attach(System.Data.Objects.DataClasses.IEntityWithKey entity);
    void AttachTo(string entitySetName, object entity);
    int? CommandTimeout { get; set; }
    DbConnection Connection { get; }
    ObjectContextOptions ContextOptions { get; }
    void CreateDatabase();
    string CreateDatabaseScript();
    EntityKey CreateEntityKey(string entitySetName, object entity);
    T CreateObject<T>() where T : class;
    ObjectSet<TEntity> CreateObjectSet<TEntity>() where TEntity : class;
    ObjectSet<TEntity> CreateObjectSet<TEntity>(string entitySetName) where TEntity : class;
    void CreateProxyTypes(IEnumerable<Type> types);
    ObjectQuery<T> CreateQuery<T>(string queryString, params ObjectParameter[] parameters);
    bool DatabaseExists();
    string DefaultContainerName { get; set; }
    void DeleteDatabase();
    void DeleteObject(object entity);
    void Detach(object entity);
    void DetectChanges();
    void Dispose();
    int ExecuteFunction(string functionName, params ObjectParameter[] parameters);
    ObjectResult<TElement> ExecuteFunction<TElement>(string functionName, params ObjectParameter[] parameters);
    ObjectResult<TElement> ExecuteFunction<TElement>(string functionName, MergeOption mergeOption, params ObjectParameter[] parameters);
    int ExecuteStoreCommand(string commandText, params object[] parameters);
    ObjectResult<TElement> ExecuteStoreQuery<TElement>(string commandText, params object[] parameters);
    ObjectResult<TEntity> ExecuteStoreQuery<TEntity>(string commandText, string entitySetName, MergeOption mergeOption, params object[] parameters);
    object GetObjectByKey(System.Data.EntityKey key);
    void LoadProperty(object entity, string navigationProperty);
    void LoadProperty(object entity, string navigationProperty, MergeOption mergeOption);
    void LoadProperty<TEntity>(TEntity entity, Expression<Func<TEntity, object>> selector);
    void LoadProperty<TEntity>(TEntity entity, Expression<Func<TEntity, object>> selector, MergeOption mergeOption);
    System.Data.Metadata.Edm.MetadataWorkspace MetadataWorkspace { get; }
    ObjectStateManager ObjectStateManager { get; }
    void Refresh(RefreshMode refreshMode, IEnumerable collection);
    void Refresh(RefreshMode refreshMode, object entity);
    int SaveChanges();
    int SaveChanges(bool acceptChangesDuringSave);
    int SaveChanges(SaveOptions options);
    ObjectResult<TElement> Translate<TElement>(DbDataReader reader);
    ObjectResult<TEntity> Translate<TEntity>(DbDataReader reader, string entitySetName, MergeOption mergeOption);
    bool TryGetObjectByKey(EntityKey key, out object value);
}
<#+
}
#>

<#+
void WriteObjectContextMockBase( EntityContainer container, CodeGenerationTools code )
{
#>
/// <summary>
/// The default concrete implementation of IObjectContext that will be used for mocking. 
/// This contains all of the <code>IObjectContext</code> members that are implemented in the 
/// concrete ObjectContext class. This class was created so these members
/// can be mocked.
/// </summary>
<#=Accessibility.ForType(container)#> abstract class ObjectContextMockBase : IObjectContext
{
    private readonly IObjectContext _objectContext;
    public ObjectContextMockBase(IObjectContext objectContext)
    {
        if (objectContext == null)
            throw new System.ArgumentNullException("objectContext");
        _objectContext = objectContext;
    }

    public virtual void AcceptAllChanges()
    {
        _objectContext.AcceptAllChanges();
    }

    public virtual void AddObject(string entitySetName, object entity)
    {
        _objectContext.AddObject(entitySetName, entity);
    }

    public virtual TEntity ApplyCurrentValues<TEntity>(string entitySetName, TEntity currentEntity) 
        where TEntity : class
    {
        return _objectContext.ApplyCurrentValues<TEntity>(entitySetName, currentEntity);
    }

    public virtual TEntity ApplyOriginalValues<TEntity>(string entitySetName, TEntity originalEntity) 
        where TEntity : class
    {
        return ApplyOriginalValues<TEntity>(entitySetName, originalEntity);
    }

    public virtual void ApplyPropertyChanges(string entitySetName, object changed)
    {
        _objectContext.ApplyPropertyChanges(entitySetName, changed);
    }

    public virtual void Attach(System.Data.Objects.DataClasses.IEntityWithKey entity)
    {
        _objectContext.Attach(entity);
    }

    public virtual void AttachTo(string entitySetName, object entity)
    {
        _objectContext.AttachTo(entitySetName, entity);
    }

    public virtual int? CommandTimeout
    {
        get { return _objectContext.CommandTimeout; }
        set { _objectContext.CommandTimeout = value; }
    }

    public virtual DbConnection Connection 
    { 
        get { return _objectContext.Connection; }
    }

    public virtual ObjectContextOptions ContextOptions
    { 
        get { return _objectContext.ContextOptions; }
    }

    public virtual void CreateDatabase()
    {
        _objectContext.CreateDatabase();
    }

    public virtual string CreateDatabaseScript()
    {
        return _objectContext.CreateDatabaseScript();
    }

    public virtual EntityKey CreateEntityKey(string entitySetName, object entity)
    {
        return _objectContext.CreateEntityKey(entitySetName, entity);
    }

    public virtual T CreateObject<T>() 
        where T : class
    {
        return _objectContext.CreateObject<T>();
    }

    public virtual ObjectSet<TEntity> CreateObjectSet<TEntity>()
        where TEntity : class
    {
        return _objectContext.CreateObjectSet<TEntity>();
    }

    public virtual ObjectSet<TEntity> CreateObjectSet<TEntity>(string entitySetName) 
        where TEntity : class
    {
        return _objectContext.CreateObjectSet<TEntity>(entitySetName);
    }

    public virtual void CreateProxyTypes(IEnumerable<Type> types)
    {
        _objectContext.CreateProxyTypes(types);
    }

    public virtual ObjectQuery<T> CreateQuery<T>(string queryString, params ObjectParameter[] parameters)
    {
        return _objectContext.CreateQuery<T>(queryString, parameters);
    }

    public virtual bool DatabaseExists()
    {
        return _objectContext.DatabaseExists();
    }

    public virtual string DefaultContainerName
    {
        get { return _objectContext.DefaultContainerName; }
        set { _objectContext.DefaultContainerName = value; }
    }

    public virtual void DeleteDatabase()
    {
        _objectContext.DeleteDatabase();
    }

    public virtual void DeleteObject(object entity)
    {
        _objectContext.DeleteObject(entity);
    }

    public virtual void Detach(object entity)
    {
        _objectContext.Detach(entity);
    }

    public virtual void DetectChanges()
    {
        _objectContext.DetectChanges();
    }

    public virtual void Dispose()
    {
        _objectContext.Dispose();
    }

    public virtual int ExecuteFunction(string functionName, params ObjectParameter[] parameters)
    {
        return _objectContext.ExecuteFunction(functionName, parameters);
    }

    public virtual ObjectResult<TElement> ExecuteFunction<TElement>(string functionName, params ObjectParameter[] parameters)
    {
        return _objectContext.ExecuteFunction<TElement>(functionName, parameters);
    }

    public virtual ObjectResult<TElement> ExecuteFunction<TElement>(string functionName, MergeOption mergeOption, params ObjectParameter[] parameters)
    {
        return _objectContext.ExecuteFunction<TElement>(functionName, mergeOption, parameters);
    }

    public virtual int ExecuteStoreCommand(string commandText, params object[] parameters)
    {
        return _objectContext.ExecuteStoreCommand(commandText, parameters);
    }

    public virtual ObjectResult<TElement> ExecuteStoreQuery<TElement>(string commandText, params object[] parameters)
    {
        return _objectContext.ExecuteStoreQuery<TElement>(commandText, parameters);
    }

    public virtual ObjectResult<TEntity> ExecuteStoreQuery<TEntity>(string commandText, string entitySetName, MergeOption mergeOption, params object[] parameters)
    {
        return _objectContext.ExecuteStoreQuery<TEntity>(commandText, entitySetName, mergeOption, parameters);
    }

    public virtual object GetObjectByKey(EntityKey key)
    {
        return _objectContext.GetObjectByKey(key);
    }

    public virtual void LoadProperty(object entity, string navigationProperty)
    {
        _objectContext.LoadProperty(entity, navigationProperty);
    }

    public virtual void LoadProperty(object entity, string navigationProperty, MergeOption mergeOption)
    {
        _objectContext.LoadProperty(entity, navigationProperty, mergeOption);
    }

    public virtual void LoadProperty<TEntity>(TEntity entity, Expression<Func<TEntity, object>> selector)
    {
        _objectContext.LoadProperty<TEntity>(entity, selector);
    }

    public virtual void LoadProperty<TEntity>(TEntity entity, Expression<Func<TEntity, object>> selector, MergeOption mergeOption)
    {
        _objectContext.LoadProperty<TEntity>(entity, selector, mergeOption);
    }

    public virtual System.Data.Metadata.Edm.MetadataWorkspace MetadataWorkspace
    {
        get { return _objectContext.MetadataWorkspace; }
    }

    public virtual ObjectStateManager ObjectStateManager
    {
        get { return _objectContext.ObjectStateManager; }
    }

    public virtual void Refresh(RefreshMode refreshMode, IEnumerable collection)
    {
        _objectContext.Refresh(refreshMode, collection);
    }

    public virtual void Refresh(RefreshMode refreshMode, object entity)
    {
        _objectContext.Refresh(refreshMode, entity);
    }

    public virtual int SaveChanges()
    {
        return _objectContext.SaveChanges();
    }

    public virtual int SaveChanges(bool acceptChangesDuringSave)
    {
        return _objectContext.SaveChanges(acceptChangesDuringSave);
    }

    public virtual int SaveChanges(SaveOptions options)
    {
        return _objectContext.SaveChanges(options);
    }

    public virtual ObjectResult<TElement> Translate<TElement>(DbDataReader reader)
    {
        return _objectContext.Translate<TElement>(reader);
    }

    public virtual ObjectResult<TEntity> Translate<TEntity>(DbDataReader reader, string entitySetName, MergeOption mergeOption)
    {
        return _objectContext.Translate<TEntity>(reader, entitySetName, mergeOption);
    }

    public virtual bool TryGetObjectByKey(EntityKey key, out object value)
    {
        return _objectContext.TryGetObjectByKey(key, out value);
    }
}
<#+
}
#>

Changez les 2 premières lignes (la 2ème étant le crochet) de WriteMockContextBody() (après le commentaire) à

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#>Mock : ObjectContextMockBase, I<#=code.Escape(container)#>
{
    public <#=code.Escape(container)#>Mock(IObjectContext objectContext)
        : base(objectContext)
    {
    }

Changez la première ligne de WriteInterface() (après le commentaire) à

<#=Accessibility.ForType(container)#> interface I<#=code.Escape(container)#> : IObjectContext

Je dois également noter que je n'ai pas encore fait beaucoup de tests avec ce système, mais j'ai fait quelques vérifications de base pour m'assurer qu'il fonctionne.

0voto

Peri Points 3670

Voici une bibliothèque qui aide à générer des données de test - http://autopoco.codeplex.com/

0voto

barrypicker Points 654

Voir le blog de Rab Hallett intitulé Générateur de contexte d'amorçage ADO.NET : Modèle Visual Studio 2010

Ici, Rab utilise un modèle T4 pour créer l'interface pour EF.

-1voto

Rob Points 603

Vous pouvez consulter este hilo sur Visual Studio pour les professionnels des bases de données. Ou RedGate a un outil similaire . Je ne connais pas d'outils gratuits permettant de faire cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X