Utiliser core data ou autre chose

chaps31chaps31 Membre
23:58 modifié dans API AppKit #1
Bonjour à  tous,
Il y a pas mal de temps j'avais commencé à  programmer un logiciel de gestion de clientèle pour mon usage perso pour commencer mais qui aurait été rapidement amené à  être distribué à  des proches, voire plus selon le résultat ;). Tout ça dans le cadre du boulot, donc pas question d'à  peu près il faut que ce soit fiable, il s'agit de la gestion d'une clientèle.

Après moulte discussion je me suis lancé avec les aides précieuses et nombreuses de feu objective-cocoa, j'imagine que les mêmes talents sont toujours par ici.

Malheureusement mon temps disponible c'est réduit à  peau de chagrin et le travail à  accomplir s'avérait dantesque expliquant mieux le prix de ces logiciels, j'ai arrêté. Ceci dit je pouvait dans un premier temps limiter les fonctions...

Et je reviens plusieurs mois plus tard, avec un problème de base, c'est le cas de le dire, la base de données, pour le même logiciel mais plus simple pour commencer.
Il en faut une avec pas mal de tables, au début j'avais opté pour Postgresql, mais depuis je n'entends qu'une chose, une base de ce type là , forcément client-serveur sans ingénieur réseau pour l'administrer il faut oublier, un indépendant seul aura un jour ou l'autre des problèmes insolubles pour lui... Bon OK, mais des logiciels qui gèrent des données il y en a pléthores qu'utilisent-ils comme base de données ?????

Revenant à  la charge, je me dis que je pourrais rejeter un coup d'oeil du coté de CoreData, si j'ai bien compris un SQLlite à  la sauce Apple, mais il y a une pierre d'achoppement qui j'espère n'est plus d'actualité (nous sommes sous snow leopard maintenant):

Peut-on avec CoreData créer une base de données multi-utilisateurs ? Est-ce que l'on peut accéder à  une telle base à  partir de plusieurs ordinateurs sur un réseau local ? En même temps bien sûr avec la base sur un seul ordi et un exemplaire de l'appli sur chaque poste  ?

Merci d'avoir lu ce long message et merci pour vos avis.

Chaps31
Un amateur mais qui aime ça ;)

Réponses

  • AliGatorAliGator Membre, Modérateur
    23:58 modifié #2
    Réponse courte : Non.
    Derrière CoreData, c'est une base SQLLite. C'est monoutilisateur.
    CoreData est plutôt fait pour manipuler un modèle de données interne à  ton application. Pas pour communiquer avec l'extérieur, donc avec une base web ou avec d'autres clients.
  • RocouRocou Membre
    23:58 modifié #3
    dans 1255621704:

    Il en faut une avec pas mal de tables, au début j'avais opté pour Postgresql, mais depuis je n'entends qu'une chose, une base de ce type là , forcément client-serveur sans ingénieur réseau pour l'administrer il faut oublier, un indépendant seul aura un jour ou l'autre des problèmes insolubles pour lui...

    J'utilise PostgreSQL depuis des années et je n'ai eu aucun souci. Et je suis loin d'être un ingénieur réseau  :)

    Il existe des installeurs très simples d'emploi, il suffit de double-cliquer pour installer et paramètrer PostgreSQL. (ce n'était effectivement pas le cas avec les versions antérieures à  la 8)
    C'est également facile de l'attaquer avec Objective_C/Cocoa, il existe des frameworks très puissants (celui que j'utilise est "minimaliste" mais gratuit). Il existe également un plugin pour RealBasic qui fonctionne très bien.

    PostgreSQL me semble être -de loin- le meilleurs choix.

    Si tu te lances, je pourrais t'aider.

    Voici ma source: http://www.postgresqlformac.com/
  • chaps31chaps31 Membre
    23:58 modifié #4
    Merci beaucoup. Bon je vais réattaquer ça en postgresql si tu en as l'expérience sans problème je vais me baser sur toi, d'aileurs ça m'arrange ;)

    Je vais regarder la version de postgre que j'avais installé, faut que je revoie mes classes de connexion car je me souviens d'un certains flou, j'étais allé un peu au pifomètre pour les méthodes du framework qui interface avec la base postgre (la même source que ton lien) ça marchait mais je n'aimais pas trop de ne pas maitriser ce que je faisais, merci encore et promis je t'appellerais à  l'aide ;)

    Salut ALiGator, tu ne dois pas te souvenir de moi mais moi très bien de tes aides nombreuses.
  • chaps31chaps31 Membre
    23:58 modifié #5
    Bon j'ai ressorti mon code, désinstallé postgre pour le réinstaller avec le package unifié . Impeccable. Je découvre le framework PGSQLKit, il me semble qu'il n'existait pas avant puisque dans mon code j'appelais directement libpq-fe.h et autres joyeusetés.

    Maintenant tout doit passer par le framework j'imagine, impec mais j'ai 2 problèmes...

    1) Les autorisations pour lancer Postgresql ne sont pas bonnes et le serveur ne se lance pas... Autant dire qu'aucune base existe encore puisqu'il ne se lance pas...
    2) Je ne trouve nulle part un descriptif précis des différentes classes de PGSQLKit et de leurs méthodes. Notamment si la méthode execCommand parle d'elle-même comment récupérer un tableau des données...

    Je veux bien un p'tit coup de pouce Rocou, merci
  • RocouRocou Membre
    23:58 modifié #6
    dans 1255701413:

    Bon j'ai ressorti mon code, désinstallé postgre pour le réinstaller avec le package unifié . Impeccable. Je découvre le framework PGSQLKit, il me semble qu'il n'existait pas avant puisque dans mon code j'appelais directement libpq-fe.h et autres joyeusetés.

    Maintenant tout doit passer par le framework j'imagine, impec mais j'ai 2 problèmes...

    1) Les autorisations pour lancer Postgresql ne sont pas bonnes et le serveur ne se lance pas... Autant dire qu'aucune base existe encore puisqu'il ne se lance pas...
    2) Je ne trouve nulle part un descriptif précis des différentes classes de PGSQLKit et de leurs méthodes. Notamment si la méthode execCommand parle d'elle-même comment récupérer un tableau des données...

    Je veux bien un p'tit coup de pouce Rocou, merci

    Pour le lancement du serveur, l'installateur installe des préférences. Tu vas dans le panneau des préférences système, tu cliques sur PostgreSQL, puis sur Start  ;)

    Pour les classes de PGSQLKit, il faut fouiller les classes, effectivement, la "doc" est maigre.

    Voici comment débuter:

    <br />PGSQLConnection *connection;<br /><br />- (id) init<br />{<br />	[super init];<br />	NSString *user = @&quot;toto&quot;;<br />	NSString *password = @&quot;titi&quot;;<br />	<br />&nbsp; &nbsp; &nbsp; &nbsp; NSString *serverName = @&quot;monAdresseIP&quot;;<br />	NSString *serverPort = @&quot;lePort&quot;;<br />	NSString *databaseName = @&quot;maBase&quot;;<br />	<br />	NSLog(@&quot;connexion en cours&quot;);<br />	connection = [[PGSQLConnection alloc] init];<br />	<br />	[connection setUserName:user];<br />	[connection setPassword:password];<br />	<br />	[connection setServer:serverName];<br />	[connection setPort:serverPort];<br />	[connection setDatabaseName:databaseName];<br />	<br />	if ([connection connect])<br />	{<br />		NSLog(@&quot;connexion ok&quot;);<br />		<br />	}<br />	<br />	<br />	return self;<br />} <br />
    


    Une mise à  jour, avec quemques pièges à  éviter:

    -(void)majDeMaTable:(NSString*)id client:(NSInteger)leclient prestation:(NSInteger)prest adrChantier:(NSString *)adr {<br />	<br />	NSString&nbsp; *query;<br />	BOOL execMaRequete;<br />	<br />	//le caractère simple quote est un caractère réservé en SQL, il faut donc le doubler<br />	NSMutableString *monAdresse = [NSMutableString stringWithFormat:@&quot;%@&quot;, adr];<br />	[monAdresse replaceOccurrencesOfString:@&quot;&#39;&quot; withString:@&quot;&#39;&#39;&quot; options:1 range:NSMakeRange(0,[monAdresse length])];<br />	<br /><br />	NSString *leClient=[NSString stringWithFormat:@&quot;%d&quot;,leclient];<br />	NSString *laPrestation=[NSString stringWithFormat:@&quot;%d&quot;,prest];<br />	<br />	query = @&quot;UPDATE locations SET client_id = &quot;;<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:leClient];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:@&quot;,prestation = &quot;];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:laPrestation];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:@&quot;,adresse = &quot;];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />						//il faut reconvertir en UTF8 avant de mettre la base à  jour<br />	query = [query stringByAppendingString:[NSString stringWithCString:[monAdresse UTF8String] encoding:NSMacOSRomanStringEncoding]];&nbsp;  <br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];	<br />	query = [query stringByAppendingString:@&quot; WHERE id = &quot;];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:id];<br />	query = [query stringByAppendingString:@&quot;&#39;&quot;];<br />	query = [query stringByAppendingString:@&quot;&quot;];<br />	<br />	execMaRequete = [connection execCommand:query];<br />	if (execMaRequete == FALSE) <br />	{<br />		[[NSAlert alertWithMessageText:[connection lastError]<br />						 defaultButton:@&quot;OK&quot;<br />					&nbsp;  alternateButton:nil<br />						&nbsp;  otherButton:nil<br />			 informativeTextWithFormat:@&quot;Prévenir l&#39;administrateur de la base&quot;] runModal] == NSAlertDefaultReturn;<br />		<br />		NSLog(@&quot;insert/update impossible %@&quot;, [connection lastError]);<br />		<br />	}	<br />}<br />
    



    Un SELECT qui va initialiser un NSPopupButton:


    //IBOutlet NSPopupButton *popClient;
    //Une table clients

    - (void) initPopClient:(id)sender<br />{<br />	NSDictionary *leDico;<br />	PGSQLRecordset *rs;<br />	<br />	[popClient removeAllItems];<br />	<br />	NSString *query = @&quot;SELECT nom, id FROM clients ORDER BY nom&quot;; <br />	<br />	rs = [connection open:query];<br />	if (rs != nil) {<br />		if (![rs isEOF])<br />		{	<br />			while (![rs isEOF])<br />			{<br />				leDico=[rs dictionaryFromRecord];<br />				NSString *caracAccentue = [[leDico valueForKey:@&quot;nom&quot;] reinterpretAsUTF8];<br />				NSMenuItem* item=[[NSMenuItem alloc] initWithTitle:caracAccentue action:NULL keyEquivalent:@&quot;&quot;];<br />				<br />				//Association de l&#39;identifiant avec le titre du PopPup (nom du client)<br />				NSString *k=[leDico valueForKey:@&quot;id&quot;];<br />				NSInteger j=[k integerValue];<br />				<br />				[item setTag:j];<br />				[[popClient menu] addItem:item];<br />				[item release];<br />				<br />				[rs moveNext];<br />				<br />			}&nbsp; &nbsp; 		<br />		}<br />	} else <br />	{<br />		NSLog(@&quot;Impossible de récupérer les données: %@&quot;, [connection lastError]);<br />	}<br />	[rs close]; <br />}<br />
    


    Un SELECT qui va remplir une NSTableView: (le code est issu de mon application)

    - (void)lesBennes:(id)sender<br />{<br />		<br />	NSString *query = @&quot;SELECT bennes.id, bennes.numero, bennes.volume, bennes.couleur, bennes.etat, bennes.origine FROM bennes ORDER BY bennes.numero&quot;;<br />	<br />	PGSQLRecordset *rs = [connection open:query];<br />	if (rs != nil) <br />	{<br />		[maListeBennes removeAllObjects];<br />		[tableViewBennes reloadData];<br />		<br />		if (![rs isEOF])<br />		{				<br />			NSInteger i=0;<br />			NSTableColumn* myTableColumn;<br />			PGSQLColumn* laColonne;			<br />			<br />			for (i=0;i&lt;[tableViewBennes numberOfColumns];i++)<br />			{			<br />				myTableColumn = [[tableViewBennes tableColumns] objectAtIndex:i];<br />				laColonne = [[rs columns] objectAtIndex:i];<br />				[myTableColumn setIdentifier:[laColonne name]]; <br />				<br />				//détermination des largeurs de colonnes<br />				switch (i) {<br />					case 0:	<br />						[myTableColumn setWidth:50]; //colonne id<br />						[myTableColumn setHeaderToolTip:@&quot;Identifiant de la benne&quot;];<br />						break;<br />					case 1:	<br />						[myTableColumn setWidth:50]; //colonne numéro<br />						[myTableColumn setHeaderToolTip:@&quot;Numéro de la benne&quot;];<br />						break;<br />					case 2:	<br />						[myTableColumn setWidth:80]; //colonne volume<br />						break;<br />					case 3:	<br />						[myTableColumn setWidth:70]; //colonne couleur<br />						[myTableColumn setHeaderToolTip:@&quot;Couleur de la benne&quot;];<br />						break;<br />					case 4:	<br />						[myTableColumn setWidth:50]; //état couleur<br />						[myTableColumn setHeaderToolTip:@&quot;état de la benne&quot;];<br />						break;<br />						<br />							<br />					default:<br />						break;<br />				}<br />				<br />				<br />			}<br />			<br />		while (![rs isEOF])<br />			{<br />				[maListeBennes addObject:[rs dictionaryFromRecord]];				<br />				[rs moveNext];<br />			}&nbsp; &nbsp;  <br />			<br />			[tableViewBennes reloadData];<br />		}<br />		<br />		<br />	} else <br />	{<br />		NSLog(@&quot;Impossible de se connecter à  la base de données&quot;);<br />	}<br />	[rs close];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />}<br />
    



    Il faudra que tu implémentes un truc de ce genre pour les problèmes de polices:

    <br />@implementation NSString (MacOSRomanToUTF8Converting)<br />- (NSString *)reinterpretAsUTF8 {<br />&nbsp; &nbsp; return [NSString stringWithUTF8String:[self cStringUsingEncoding:NSMacOSRomanStringEncoding]];<br />}<br /><br />@end<br /><br />@implementation NSString (UTF8toMacOSRomanConverting)<br />- (NSString *)reinterpretAsMacOSRoman {<br />&nbsp; &nbsp; return [NSString stringWithUTF8String:[self cStringUsingEncoding:NSUTF8StringEncoding]];<br />}<br />@end<br />
    



  • chaps31chaps31 Membre
    23:58 modifié #7
    Merci beaucoup  Je vais bien utiliser tout ça..

    Une autre question j'ai un gros problème... J'ai installé postgresql avec l'installeur unifié, il crée un script dans les startupItems qui lance le serveur au démarrage du mac, sauf que... Mac OSX m'envoie un message d'alerte m'informant qu'à  cause d'un problème de sécurité il ne lance pas le script dans les startupItems...

    J'ai cherché partout sur le net, réparé les autorisations, fait un chown dans le terminal avec -R a+r-x, rien n'y fait mac osx refuse de lancer le script. Par contre "à  la main" dans le terminal avec un sudo aucun problème...

    La misère, tu as une idée ?

    Merci encore
  • zoczoc Membre
    23:58 modifié #8
    sudo chmod -R 755 /Library/StartupItems/<tonstartupitem>
    sudo chown -R root:wheel /Library/StartupItems/<tonstartupitem>
  • chaps31chaps31 Membre
    octobre 2009 modifié #9
    dans 1255941035:

    sudo chmod -R 755 /Library/StartupItems/<tonstartupitem>
    sudo chown -R root:wheel /Library/StartupItems/<tonstartupitem>


    MERCI, ça marche impec... heu.... Tu peux m'expliquer ce que ça a fait ? Merci ;)
  • AliGatorAliGator Membre, Modérateur
    23:58 modifié #10
    Le chown a simplement modifié le possesseur de <tonstartupitem> pour que ce soit dorénavant l'utilisateur "root" (appartenant au groupe "wheel"), autrement dit en quelques sortes l'utilisateur représentant "le système", qui lance les services au démarrage.
    Comme ça le système a le droit de lancer <tonstartupitem> puisqu'il en est maintenant le possesseur.
    De plus, le chmod a donné les droits d'écriture, lecture et exécution au possesseur (donc à  "root"), et les droits de lecture et exécution au reste du monde (mais pas d'écriture).
  • chaps31chaps31 Membre
    23:58 modifié #11
    Merci bcoup
  • yoannyoann Membre
    23:58 modifié #12
    Pensez quand même dans vos déploiement à  remplacer les StartupItem par des LaunchServices. ça fait depuis Leopard que les StartupItem sont obsolètes, ça va finir par dégager, donc autant se placer sur le bon système. D'autant plus que launchd permet plus de chose (entre autre démarrer votre service uniquement lorsqu'il reçoit un accès réseau)
  • chaps31chaps31 Membre
    23:58 modifié #13
    Ce que tu dis dépasse mes connaissances d'amateur même si je le comprend très bien, mais dans mon cas il s'agit de l'installeur Postgresql qui met le script à  cette place, faudrait que je le déplace après son installation et surtout que je potasse les LaunchServices ;) Merci de l'info
  • yoannyoann Membre
    23:58 modifié #14
    Tant que ça marche comme ça on peut dire que c'est bon, pour autant le jour où ça ne marche plus ça serait bête d'attendre que le mec qui a fait le package PgSQL réagisse. C'est pas obligatoire sur le court terme mais a prévoir pour faire propre disons

    Pour les LaunchServices c'est juste un XML où tu dis au système de lancer tel commande en tant que tel utilisateur a un moment précis (lancement de la machine appel périodique, lors d'un accès réseau sur un port particulier etc)

    C'est pas très complexe a mettre en oeuvre et une fois qu'on connait les capacité du truc ça peut donner des idées pour se simplifier la vie
  • ClicCoolClicCool Membre
    23:58 modifié #15
    On peut dire que t'es tétu Yoann !  ;)

    Mais ça vallait le coup, et je te remercie d'avoir attiré notre attention sur cette nouveauté (d'après 10.4).
    C'est vrai qu'avec les cron.tab, en dehors d'être pénible à  utiliser, nos tâches de fond étaient purement et simplement oubliées si le portable était fermé à  l'instant crucial.
    Et la possibilité de guetter une évènement déclencheur (connexion ...) est trop géniale.
    Je suppose que TimeMachine utilise ça pour se lancer quand le disque de sauvegarde est connecté ou que TimeCapsule est détectée...
    Bref, ça ouvre des horizons !!!  :adios!:


    Pour ceux que ça interesse: System Startup Programming Topics
Connectez-vous ou Inscrivez-vous pour répondre.