1
votes

Comment gérer avec élégance les colonnes NOT NULL SQL Server dans les formulaires Access?

J'ai un front-end MS Access lié à une base de données SQL Server.

Si une colonne est requise, alors la chose naturelle à faire est d'inclure NOT NULL dans la définition de cette colonne (au niveau de la base de données). Mais cela semble créer des problèmes du côté de l'accès. Lorsque vous liez un formulaire à cette table, le champ lié à cette colonne finit par être assez peu convivial. Si l'utilisateur efface le texte de ce champ, il ne pourra pas quitter le champ tant qu'il n'aura pas saisi quelque chose. Chaque fois qu'ils essaieront de quitter le champ alors qu'il est vide, ils obtiendront cette erreur:

Vous avez essayé d'attribuer la valeur Null à une variable qui n'est pas un type de données Variant.

C'est un message d'erreur vraiment terrible - même pour un développeur, sans parler du pauvre utilisateur. Heureusement, je peux le faire taire ou le remplacer par un meilleur message avec un code comme celui-ci:

Private Sub Form_Error(DataErr As Integer, Response As Integer)
    If DataErr = 3162 Then
        Response = acDataErrContinue
        <check which field is blank>
        MsgBox "<some useful message>"
    End If
End Sub

Mais ce n'est qu'une solution partielle. Pourquoi l'utilisateur ne devrait-il pas pouvoir quitter le terrain? Aucune interface utilisateur moderne décente ne restreint cette concentration (pensez aux sites Web, aux applications téléphoniques, aux programmes de bureau - quoi que ce soit, vraiment). Comment contourner ce comportement d'Access en ce qui concerne les champs obligatoires?

Je publierai les deux solutions de contournement que j'ai trouvées comme réponse, mais j'espère qu'il y a de meilleures façons que j'ai négligées. p>


0 commentaires

3 Réponses :


-1
votes

Les deux solutions de contournement que j'ai proposées sont:

  1. Ne rendez pas la colonne de base de données NOT NULL et ne comptez pas uniquement sur les formulaires Access pour l'intégrité des données plutôt que sur la base de données. Les lecteurs de cette table seront surchargés par une colonne ambiguë qui ne contiendra pas de valeurs nulles en pratique (tant que le code de validation de formulaire est valide) mais pourrait contenir des valeurs nulles en théorie en raison de la façon dont la colonne est définie dans la base de données. Ne pas avoir cette garantie à 100% est gênant mais peut suffire en réalité.

    Verdict : facile mais bâclé - procédez avec prudence

  2. Abuser du fait que les liens d'Access vers des tables externes doivent être actualisés manuellement. Rendez la colonne NULL dans SQL Server, actualisez le lien dans Access, puis rendez à nouveau la colonne NOT NULL dans SQL Server - mais cette fois, n'actualisez pas le lien dans Access.

    Le résultat est qu'Access ne réalisera pas que le champ est NOT NULL et, par conséquent, laissera l'utilisateur seul. Ils peuvent se déplacer dans le formulaire comme ils le souhaitent sans obtenir l'erreur cryptique 3162 ou avoir leur focus restreint. S'ils essaient d'enregistrer le formulaire alors que le champ est toujours vide, ils recevront une erreur ODBC provenant de la base de données sous-jacente. Bien que ce ne soit pas souhaitable, cela peut être évité en vérifiant les champs vides dans Form_BeforeUpdate () et en fournissant à l'utilisateur un message d'erreur intelligible à la place.

    Verdict : meilleur pour l'intégrité des données mais aussi plus pénible à maintenir, sorte de hacky / étonnant et fragile en ce sens que si quelqu'un actualise le lien de la table, l'erreur redoutée / restriction de focus reviendra - là encore, ce scénario du pire des cas n'est pas catastrophique car la conséquence est simplement la gêne de l'utilisateur, pas des problèmes d'intégrité des données ou la rupture de l'application


7 commentaires

Avant de peaufiner le back-end pour faire fonctionner le front-end, je suggérerais de choisir un front-end alternatif ... abandonnez Access si l'interface utilisateur est si mauvaise que vous envisagez d'affaiblir un bon design. Si vous êtes nouveau dans Access et que vous ne pouvez déjà pas tolérer un tel comportement, vous trouverez probablement de nombreuses autres fonctionnalités mal conçues contrairement à une «conception d'interface utilisateur moderne décente». (BTW, je suis entièrement d'accord avec votre description du comportement, donc quand Access a été requis à un moment donné de mon travail, il m'a fallu beaucoup de temps pour surmonter la conception de l'interface utilisateur Access-esque. J'essaye juste de vous sauver le chagrin.)


@CPerkins Ouais, je suis avec toi. Malheureusement, je suis coincé avec Access pour le moment car c'est une grande application préexistante que je n'ai pas le temps de reconstruire à partir de zéro.


Autoriser ZLS AND nulls est un cauchemar. À moins que le nouveau code d'enregistrement ne définisse toujours toutes ces colonnes comme ZLS, vous êtes foutu. Le formulaire CRUD typique n'éditera pas ou n'aura même pas toutes les colonnes pour l'édition. Alors maintenant, vous ajoutez et des tonnes de colonnes seront nulles et des tonnes ZLS. Adopter une norme de codage pour que les colonnes vides soient toujours nulles est une façon FANTASTIQUE d'aller. SQL n'a pas de paramètre comme Oracle pour rendre toutes les valeurs nulles comme ZLS. Votre tentative de fuite à partir des valeurs nulles échouera la première fois que vous effectuez une jointure à gauche très courante. Cela entraînera que les lignes enfants soient toutes nulles et que vous codiez de toute façon pour les valeurs nulles.


@ AlbertD.Kallal Permettez-moi de clarifier. La colonne n'est pas censée contenir des valeurs nulles ou des chaînes de longueur nulle. Le champ est obligatoire sur le formulaire. Par conséquent, il n'est pas pertinent de se demander s'il est préférable de représenter les espaces sous forme de valeurs nulles ou de chaînes de longueur nulle. De plus, je n'ai jamais dit que c'était un champ de chaîne - c'était votre hypothèse. La question est simplement la suivante: étant donné un formulaire avec une colonne obligatoire, comment donner à l'utilisateur une bonne expérience de validation au lieu de restreindre de manière désagréable le focus à ce champ alors qu'il est vide - une étrange bizarrerie que je n'ai jamais vue en dehors de MS Access.


@ AlbertD.Kallal Je viens de mettre à jour ma réponse pour la clarifier un peu et j'ai également mis à jour la question pour indiquer clairement que c'est une colonne obligatoire. J'espère que vous ne le considérez pas toujours comme un vote défavorable (si c'était vous).


Je n'ai pas voté contre. C'est un problème désagréable avec Access. La recommandation d'éviter les nulls comme vous le dites est un débat pour les universitaires et un débat pour un autre jour. Pour moi, les colonnes vides sont nulles - fin de l'histoire. Il faut adopter un standard pour leur application donnée. Ainsi, pour les applications pratiques du monde réel, il est préférable de supposer que toutes les colonnes vides sont enregistrées sous forme de valeurs nulles - c'est particulièrement le cas avec les applications serveur Access + SQL. Le serveur Access + SQL ne fonctionne tout simplement pas bien avec ZLS. L'inconvénient de ZLS + Null qui s'infiltre dans une application est un cauchemar. Toute jointure gauche introduira de toute façon beaucoup de valeurs nulles.


Il faut adopter un standard et tout est soit ZLS soit nul. Cependant QUAND travailler avec Access si on PEUT faire un choix, alors tous vides comme des valeurs nulles est à coup sûr la voie à suivre. Travailler et migrer l'accès au serveur SQL pendant plus de 10 ans, supposer et choisir que toutes les colonnes vides autorisent les valeurs nulles est le meilleur choix. Pour les colonnes de nombre, bit, je les attribue par défaut à 0. Mais pour les colonnes de texte, il est préférable de simplement null. Le problème, c'est quand on n'a pas le choix. Ma seule suggestion ici est de faire tapis avec des valeurs nulles. Si on ne peut pas faire cela, ils sont dans une course très difficile.



0
votes

Plutôt que de changer les définitions de table backend ou d'essayer de "tromper" l'accès avec des définitions de table liées désynchronisées, changez simplement le (s) contrôle (s) pour toute colonne "NOT NULL" d'une liée à une non liée field (c'est-à-dire Effacez la propriété ControlSource et changez le nom du contrôle - en ajoutant un préfixe par exemple - pour éviter des collisions ennuyeuses avec le nom du champ sous-jacent. ).

Cette solution sera certainement moins "cassante", mais elle vous demandera d'ajouter manuellement du code de liaison à un certain nombre d'autres événements Form. Pour fournir une expérience cohérente comme les autres contrôles d'accès et formulaires, j'implémenterais au moins Form_AfterInsert (), Form_AfterUpdate (), Form_BeforeInsert (), Form_BeforeUpdate (), Form_Current (), Form_Error (), Form_Undo () .


P.S. Bien que je ne me souvienne pas d'avoir vu un message d'erreur aussi mal rédigé auparavant, le comportement général décrit est identique pour une colonne de table Access avec Required = True , qui est l'équivalent de l'interface utilisateur d'accès de NOT NULL critères de colonne.


6 commentaires

J'apprécie cette suggestion. C'est intéressant mais semble complexe. Je ne suis pas tout à fait sûr de ce que je mettrais dans chacun de ces gestionnaires d'événements. Pourriez-vous m'expliquer ou m'indiquer une bonne ressource?


Je ne suis pas en mesure de fournir un code détaillé pour le moment, mais le concept général est que le contrôle doit être explicitement chargé, enregistré et validé dans le code. Par exemple, dans OnCurrent (), il devrait y avoir quelque chose comme txtID.Value = Me.ID en supposant que l'ID de colonne est sélectionné dans la requête RecordSource du formulaire. Honnêtement, il y a tellement de détails à prendre en compte et de contrôle des propriétés à définir / valider, que la technique globale est au-delà des réponses à cette question. Dans ce cas, «élégant» ne veut pas dire rapide ou facile.


Pour mémoire, permettez-moi de souligner que c'est la bonne façon de modifier le comportement par défaut des formulaires Access. D'autres astuces finiront probablement par nécessiter du code supplémentaire, des problèmes de maintenance ou des formulaires bogués.


Une réponse creux. C'est soit votre suggestion, soit vous optez pour des valeurs nulles pour le côté serveur SQL par défaut (toutes les colonnes de texte autorisent les valeurs nulles). Pour une petite application, votre suggestion peut fonctionner. Pour une application volumineuse, l'adoption de nulls côté serveur sql sera beaucoup moins de travail. Je n'ai pas de jolie réponse ici.


@ AlbertD.Kallal Je suis d'accord pour dire qu'autoriser les nulls sur le backend peut parfois fonctionner, mais je répondais non seulement à la question globale, mais spécifiquement à la propre réponse de l'OP qui ne contenait que de mauvaises astuces pour tromper la validation par défaut du formulaire d'accès. Pour une grande application, une meilleure suggestion est de choisir autre chose qu'Access, surtout si les formulaires ne se comportent pas de manière acceptable ... mais c'est ce que j'ai déjà suggéré dans les commentaires au PO. Je grince des dents à affaiblir le backend juste pour satisfaire une mauvaise interface utilisateur. Il est possible d'appliquer de bonnes règles de données backend et d'avoir une excellente interface utilisateur.


Mon vb.net et mes applications asp.net suivent cette norme et cette suggestion. Le bœuf et l'argument MAJEUR pour ne pas autoriser les valeurs nulles est que c'est supposé être une douleur pour les développeurs. Mais ensuite, il y a des colonnes de date (beaucoup de valeurs nulles) et TOUTE jointure gauche (qui, comme je le prétends, est d'environ 80% d'entre elles), puis vous avez à nouveau des tonnes de colonnes nulles. Vous allez devoir traiter des valeurs nulles partout dans une application. En tant que développeur, il est donc préférable d'assumer et de choisir un design qui n'a PAS de chaînes ZLS partout. Je trouve que ZLS est un problème bien pire. Ma suggestion ne se limite pas aux applications Access.



0
votes

Je suggérerais que vous puissiez simplement modifier toutes les tables du serveur SQL pour autoriser les valeurs nulles pour ces colonnes de texte. Pour bit, les colonnes de nombres les mettent par défaut à 0 côté serveur sql. Alors que notre industrie a tendance à suggérer d'éviter les valeurs nulles, et que de nombreux développeurs souhaitent ÉGALEMENT éviter les valeurs nulles, ils décochent donc l'autorisation du côté serveur SQL des nulls. Le problème est que vous ne pouvez jamais vous enfuir et éviter de toute façon des tonnes de valeurs nulles. Prenez une simple requête de dire clients et leur dernier numéro de facture + le total de la facture. Mais bien sûr, TRÈS courant serait d'inclure des clients qui n'ont rien acheté dans cette liste (des clients sans ivoices encore, ou des clients sans aucun des milliards de cas possibles où les enregistrements enfants n'existent pas encore. Je trouve environ 80% ou PLUS de mes quires dans une application typique sont des jointures GAUCHE. Cela signifie que tout enregistrement parent sans enregistrement enfant renverra TOUTES ces colonnes enfants comme nulles. Vous allez travailler avec, et voir, et DEVEZ gérer des tonnes et des tonnes de NULL dans une application MÊME si vos conceptions de table n'autorisent JAMAIS les valeurs nulles. Vous ne pouvez pas les éviter - vous ne pouvez tout simplement pas vous échapper de ces vilaines valeurs nulles. ), alors de loin, la meilleure solution consiste simplement à autoriser et à définir toutes les colonnes de texte comme autorisant les valeurs nulles. Je peux également affirmer que si un concepteur d'application ne met pas les pieds sur terre et fait un choix judicieux pour TOUJOURS utiliser des valeurs nulles, alors la pénétration des données NULLS et ZLS est un mu ch pire problème à traiter.

Le problème et le problème deviennent très désagréables et douloureux si l'on n'a pas le contrôle ou que l'on ne peut pas faire ce choix.

En fin de compte, Access ne fonctionne tout simplement pas avec le serveur SQL et le choix d'autoriser les colonnes ZLS.

Pour une migration vers un serveur SQL (et je les fais depuis plus de 10 ans), il est indiscutable que le choix des nulls pour toutes les colonnes de texte est de loin le choix le plus facile ici. p>

Je vous recommande donc de ne pas essayer de coder autour de ce problème, mais simplement de changer toutes vos tables SQL par défaut et d'autoriser les valeurs nulles pour les colonnes vides.

Le résultat de ce qui précède peut nécessiter quelques modifications mineures de l'application, mais la douleur et l'effort seront beaucoup moins que d'essayer de corriger ou de coder pour accéder à un support médiocre (en fait non support) des colonnes ZLS lorsque travailler avec le serveur SQL.

Je noterai également que cette suggestion n'est pas une bonne suggestion, mais c'est simplement la meilleure suggestion étant donné les limites du fonctionnement d'Access avec le serveur SQL. Certains systèmes de base de données (oracle) ont un paramètre global qui dit que chaque null doit être converti en ZLS et donc vous n'avez pas à vous soucier de dire ceci:

select * from tblCustomers where (City is null) or (City is = "")

Comme ci-dessus montre, l'instant où vous autorisez à la fois ZLS et null dans votre application est le MÊME instant que vous avez créé un énorme désordre monstre. Et le débat scientifique sur la non-définition des valeurs nulles est simplement un débat pour un autre jour.

Si vous développez avec Access + SQL Server, alors il faut adopter une approche standard - je recommande que cette approche soit simplement que toutes les colonnes de texte sont définies sur autorise les valeurs nulles et les colonnes de date. Pour les nombres et les colonnes de bits, définissez-les par défaut sur 0.

Cela revient à moins de peine et de travail. Soit essayez quelques modifications MAJEURES dans l'application et dites dé-lier les colonnes de texte (cela peut être une énorme quantité de travail).

Ou

Supposons simplement et définissez toutes les colonnes de texte pour autoriser nulls. C'est le bailleur d'un mal dans ce cas, et il faut se conformer au sac d'outils qui vous a été remis.

Donc je n'ai pas de solution de contournement, mais seulement un chemin et un cours prendre cela entraînera le moins de travail et de douleur. Cette voie la moins pénible consiste à autoriser les nulls. Cette suggestion ne fonctionnera bien sûr que si l'on peut faire ce choix.


0 commentaires