IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Unity fonctionne en local mais pas sur le serveur


Sujet :

C#

  1. #1
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut Unity fonctionne en local mais pas sur le serveur
    Bonjour,

    Dans le cadre d'API OData nous utilisons Unity pour injecter le bon contexte de connexion à une base de données dans le constructeur de certains de nos contrôleurs ODATA.

    Tout fonctionne sur nos machines de développement mais pas sur le serveur sur lequel nous déployons les API où avons le message "<Error><Message>An error has occured</Message></Error>".
    Je suis certain qu'il s'agit bien d'un problème lié à Unity et non d'accès à la source de données car nous avons certains contrôleur qui n'ont pas besoins d'accéder à la base.

    Sur un tel contrôleur (sans constructeur) qui ne plante pas, j'en ajoute un de la manière suivante mais qui passent en paramètre la repository mais ne l'utilise pas, et sa plante :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public XXXController(IODataRepository<XXX> repository)
    {
       internalRepository = repository;
    }

    Bref, je ne suis pas familier avec Unity et mon collègue est aux abonnés absents

    De ce que j'ai pu voir la registration est faite de cette manière (la méthode Register est appelé depuis le Startup)
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    public static class UnityConfig
        {
            // Configuration du résolveur de dépendance 
     
            public static UnityContainer Container { get; set; }
     
            public static void Register(HttpConfiguration config)
            {
                Container = new UnityContainer();
     
                Container.RegisterType<ODataContext>(
                    new InjectionConstructor(
                        new ResolvedParameter(typeof(SqlConnectionStringBuilder), "builder")));
     
                /* CA1506 (Maintenance)
                 * Avoid excessive coupling */
                RegisterCommon();
                RegisterAccounting();
                RegisterInternalManagement();
     
                Container.RegisterType<ConnectionStringDataPathHandler>();
     
                // On initialise la valeur à vide et null
                Container.RegisterInstance("Folder", String.Empty);
                Container.RegisterInstance<SqlConnectionStringBuilder>("builder", new SqlConnectionStringBuilder());
     
                if (config != null)
                {
                    config.DependencyResolver = new UnityResolver(Container);
                }
            }
     
            private static void RegisterCommon()
            {
                /* CA2000 (Reliability)
                 * Call Dispose on object before losing scope */
                RegisterType<IODataRepository<XXX>, ODataRepository<XXX>>();
                ....
            }
     
            /* CA2000 (Reliability)
             * Call Dispose on object before losing scope */
            [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
                Justification = "UnityContainer becomes responsible for the release of the manager")]
            private static void RegisterType<TFrom, TTo>() where TTo : TFrom
            {
                Container.RegisterType<TFrom, TTo>(new HierarchicalLifetimeManager());
            }
        }

    Il y a également une classe UnityResolver :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    public class UnityResolver : IDependencyResolver
        {
            public UnityResolver(IUnityContainer container)
            {
                if (container == null)
                {
                    throw new ArgumentNullException(nameof(container));
                }
     
                internalContainer = container;
            }
     
            public object GetService(Type serviceType)
            {
                try
                {
                    return internalContainer.Resolve(serviceType);
                }
                catch (ResolutionFailedException r)
                {
                    return null;
                }
            }
     
            public IEnumerable<object> GetServices(Type serviceType)
            {
                try
                {
                    return internalContainer.ResolveAll(serviceType);
                }
                catch (ResolutionFailedException)
                {
                    return new List<object>();
                }
            }
     
            public IDependencyScope BeginScope()
            {
                var child = internalContainer.CreateChildContainer();
                return new UnityResolver(child);
            }
     
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
     
            protected virtual void Dispose(bool disposing)
            {
                internalContainer.Dispose();
            }
     
            /* CA1051 (Design)
             * Do not declare visble instance fields */
            protected IUnityContainer Container
            {
                get { return internalContainer; }
                set { internalContainer = value; }
            }
     
            private IUnityContainer internalContainer;
        }

    La classe ODataRepository n'a rien d'exceptionnel :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     public class ODataRepository<T> : IODataRepository<T>
            where T : class
        {
            #region Private Fields
     
            private readonly ODataContext _currentContext;
     
            #endregion
     
            #region Constructor
            public ODataRepository(ODataContext context)
            {
                _currentContext = context;
            }
            #endregion
     
            #region IODataRepository                
     
            public IQueryable<T> SelectAll()
            {
                return DataSet.AsQueryable();
            }
     
            public SingleResult<T> SelectByKey(String key)
            {
                PropertyInfo primaryKeyProperty = null;
                var properties = typeof(T).GetProperties();
                foreach(var property in properties)
                {
                    var attribute = property.CustomAttributes.FirstOrDefault(it => it.AttributeType.Name.Equals("KeyAttribute"));
     
                    if (attribute != null)
                    {
                        primaryKeyProperty = property;
                        break;
                    }
                }
     
                if (primaryKeyProperty != null)
                {
                    var parameter = Expression.Parameter(typeof(T));
                    var body = Expression.Equal(Expression.Property(parameter, primaryKeyProperty), Expression.Constant(key));
                    var expression = Expression.Lambda<Func<T, Boolean>>(body, parameter);
                    return SingleResult.Create(DataSet.Where(expression).AsQueryable());
                }
     
                return null;
            }
            #endregion
     
            protected IDbSet<T> DataSet
            {
                get { return _currentContext.CreateSet<T>(); }
            }
     
            public ODataContext Context
            {
                get { return _currentContext; }
                set { }
            }
        }

    Bref, ça fonctionne en local même après un clean et un rebuild mais ça ne fonctionne plus une fois sur le serveur.
    J'ai vérifié le Web Deploy et il contient bien les DLL de Unity.

    Encore une fois, ce code n'est pas le mien et je peine à comprendre comment ça fonctionne.
    D'après les tutos que j'ai lu et ce que j'en ai compris, je ne vois pas où est le problème surtout que ça fonctionne en local, ça doit donc être une question d'environnement mais quoi ?

    Merci pour votre aide.

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Bon, il semblerait que EntityFramework tente d'établir une connexion avant même que j'utilise le contexte.
    Le problème venait de l'absence de la DLL EntyFramework.SqlServer dans le web deploy fabriqué par TFS Build alors que le build local me la génère à chaque fois.

    Pour résoudre j'ai du ajouter une référence à System.Data.Entity et ajouter une ligne bidon dans mon code utilisant System.Data.Entity.SqlServer.SqlProviderServices.
    Sinon, rien à faire TFS build ne veut pas la générer.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. window.close(); fonctionne en local mais pas sur le serveur
    Par mickey2705 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 27/06/2014, 08h32
  2. sessions fonctionnant en local mais pas sur un serveur
    Par lowvensky dans le forum Langage
    Réponses: 14
    Dernier message: 13/09/2013, 11h16
  3. [RegEx] Regex qui fonctionne en local mais pas sur le serveur
    Par lecroquant dans le forum Langage
    Réponses: 3
    Dernier message: 10/01/2012, 16h01
  4. [Smarty] Fonctionne en local mais pas sur le serveur
    Par student_ dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 28/11/2010, 10h37
  5. Réponses: 4
    Dernier message: 14/03/2006, 10h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo