Archiv für den Monat August 2011

Inversion of Control and Entity Framework

Today i want to show you my approach to resolve the requested entity framework object context at runtime. Starting point:

  • First, i want to have just one implementation of an IUnitOfWork to resolve any kind of repository like Repository<Order>
  • Second, my unit of work should autodiscover the proper context for my requested type of domain model as i have different databases and object contexts. For example, Order is a domain object of my domain model (namespace Domain.ComWork) according to the context ‘comwork’, which is mapping to the database ‘comwork’. There’s another domain object like Customer in my domain model (namespace Domain.MyHeco) according to the context ‘myheco’, which is mapping to the database ‘myheco’.

So how can i achieve this? I will use an IoC container like Castle.Windsor. You can add it to your Visual Studio project by the nuget command “install-package Castle.Windsor”. I want to mention that this scenario needs a little bit of advanced IoC techniques because the dependent component has to be resolved at runtime. So you’re not able to register a dedicated component for an interface. Instead you’ve got to use a facility. Allright, so we tell the container that we will register a facility:

   1: container.AddFacility<TypedFactoryFacility>();

 

In line 1 we tell the container that it has to load the necessary infrastructure for facilities. Let’s take a look at the registration process. Here’s my method that will return me an IEnumerable of IRegistration.

   1: static IEnumerable<IRegistration> Components()

   2: {

   3:     yield return Component

   4:         .For<IContextFactory>()

   5:         .AsFactory(c => c.SelectedWith<ContextFactoryHandlerSelector>());

   6:     yield return Component

   7:         .For<ContextFactoryHandlerSelector>();

   8:     yield return Component

   9:         .For<IUnitOfWork>()

  10:         .ImplementedBy<UnitOfWork>();

  11:     yield return Component

  12:       .For<ComWorkContext>()

  13:       .Named("comworkcontext");

  14:     yield return Component

  15:       .For<MyHecoContext>()

  16:       .Named("myhecocontext");

  17: }

 

Here’s the good news: Castle Windsor has an out of the box feature that creates you the needed factory. In other words: The container creates automatically the factory. You’re code is unaware of the container. Take a look at this article. If you want to use this you’ve have to follow some conventions. In my approach i decided to develop my own implementation to follow my own convetions. Take a look at line 5.  With “.AsFactory” i tell the container that i don’t register a concrete implementation for that service (IContextFactory). If i would follow the conventions of Castle.Windsor calling AsFactory() would be enough.

Here’s the code for my own implementation of a TypedFactoryComponentSelector (this would be auto generated by using just AsFactory without parameters):

   1: public class ContextFactoryHandlerSelector : ITypedFactoryComponentSelector

   2: {

   3:     public TypedFactoryComponent SelectComponent(MethodInfo method, 

   4:         Type type, object[] arguments)

   5:     {

   6:         var requestFor = method.GetGenericArguments().First();

   7:         

   8:         var @namespace = string.Format("{0}context", 

   9:             requestFor.Namespace.ToLower()

  10:             .Replace("domain.",""));

  11:         

  12:         return new TypedFactoryComponent(@namespace, method.ReturnType, null);

  13:     }

  14: }

 

My convention is pretty simple: The name of my object context is the same as the namespace of my model without the string “domain.” and with “context” appended.

Sample: Full name of my domain object: “domain.comwork.order”

  • use just the namespace –> domain.comwork
  • replace domain –> comwork
  • add context –> comworkcontext

I have two kind of domain models (domain.comwork and domain.myheco) so i need two contexts (comworkcontext and myhecocontext). Every context is registered:

   1: yield return Component

   2:   .For<ComWorkContext>()

   3:   .Named("comworkcontext");

   4: yield return Component

   5:   .For<MyHecoContext>()

   6:   .Named("myhecocontext");

 

Now we’ve got it: We have a facility that invokes a call to my self implemented factory if a service (defined in the interface IContextFactory) is requested. The factory returns the name of the needed context at runtime. My Interface looks like this:

   1: public interface IContextFactory

   2: {

   3:     ObjectContext GetContextFor<T>();

   4: }

And here’s the generic part. If i call GetContextFor<domain.comwork.order> i will get my comworkcontext. If i call GetContextFor<domain.myheco.customer> i will get my myhecocontext.

The last step is to inject the factory in my UnitOfWork. Nothing easier than that:

   1: public class UnitOfWork : IUnitOfWork

   2: {

   3:     private readonly IContextFactory _factory;

   4:  

   5:     public UnitOfWork(IContextFactory factory)

   6:     {

   7:         _factory = factory;

   8:     }

   9:  

  10:     //here you would return an IRepository<T>

  11:     //this is just a sample code

  12:     public void GetRepository<T>() where T : class 

  13:     {

  14:         Console.WriteLine(_factory.GetContextFor<T>().GetContextName());

  15:     }

  16: }

 

And how can i resolve my concrete UnitOfWork in my program?

   1: static class Program

   2: {

   3:     static void Main(string[] args)

   4:     {

   5:             using (var container = new WindsorContainer())

   6:             {

   7:                 container.AddFacility<TypedFactoryFacility>();

   8:                 container.Register(Components().ToArray());

   9:  

10: container.Resolve<IUnitOfWork>()

.GetRepository<Domain.ComWork.Foo>();

11: container.Resolve<IUnitOfWork>()

.GetRepository<Domain.MyHeco.Bar>();

  12:             }

  13:     }

  14:  

  15:     static IEnumerable<IRegistration> Components()

  16:     {

  17:         //Registrations...

  18:     }

  19: }

Advertisements

Gehaltsverhandlungen – Teil 2

Bereits im Juni hatte ich hier zu diesem Thema gebloggt. Nachdem ich nun das Buch 30 Minuten für Ihre Gehaltserhöhung von Martin Wehrle gelesen habe, wollte ich noch einige wichtige Punkte ergänzen:

Idealerweise führt der Mitarbeiter kontinuierlich ein Leistungstagebuch, welches die Grundlage zur Erstellung einer Leistungsmappe ist. Ich persönlich tendiere aber dazu, dass die “Mappe” lediglich 1-2 Seiten umfassen sollte. Außerdem rate ich selbst dann zu besagtem Leistungsprotokoll, wenn man einen Vorgesetzten hat, der ausgiebig und oft lobt, da das Gedächtnis so seine Tücken aufweist. Zu diesen Führungskräften kann ich mich übrigens nicht zählen, weil ich vom Loben nur im beschränkten Maße etwas halte (dazu ein anderes Mal mehr).

Neben dem eigentlichen Festgehalt, welches schnell seine raue Alltagsfratze in Form von Steuern und Sozialabgaben zeigt, gibt es viele interessante Alternativen, die sowohl für den Arbeitnehmer als auch Arbeitgeber Vorteile aufweisen. Hierzu eine kurze Auflistung, was denn so alles in Frage kommen könnte:

  • Prämie: Einmalzahlung für eine definierte Individualleistung
  • Bonus: Entspricht bei einer GmbH i.d.R. der Gewinnbeteiligung
  • Gratifikation: Einmalzahlung aus besonderem Anlass, z.B. Weihnachtsgeld (wird auch nachträglich ausgezahlt)
  • Provision
  • Belegschaftsaktien
  • Firmenwagen: Hierbei werden z.B. keine Sozialabgaben fällig!
  • Fahrtkosten: Sind niedrig besteuert
  • Direktversicherung: Immer wieder sinnvoll aus meiner Sicht
  • Weiterbildung: Steigert den eigenen Marktwert + die Leistungsfähigkeit im Job
  • Alltagszuschüsse: Zum Beispiel für Handy, Internet, Fitness Club
  • Belegschaftsrabatt

 

Thema Gehaltssprünge:

Speziell dabei habe ich festgestellt, dass viele sehr unsicher sind, was das angeht. Normalerweise liegen diese zw. 3 und 10 Prozent, wobei 10 Prozent recht ambitioniert ist. Bei weniger als 3 Prozent frisst einem die Inflation das bisschen Netto wieder auf. Zwischen 10 und 20 Prozent liegt die Grenze, die vorwiegend dann angekratzt wird, wenn man z.B. eine Projekt-, Team- oder Abteilungsleitung übernimmt.

 

Thema Verhandlungsstrategie:

Nach einer Gehaltserhöhungen sollte man in der Regel zw. 12 und 18 Monaten die Füße stillhalten. Deswegen ist es wichtig, dass man als Angestellter auch mit der Erhöhung für diesen Zeitraum leben kann. In anfangs erwähntem Buch werden ein Minimal- (=Schmerzgrenze), ein Maximal- und ein Alternativziel (z.B. eine der oben aufgelisteten Möglichkeiten) vorgeschlagen. Das halte ich für sinnvoll und gebe diese Empfehlung deshalb so weiter.

 

Bei Argumenten für die eigene Position sollten immer eine der folgenden Kriterien bedient werden:

  • Die Firma spart Geld durch mich
  • Ich bringe der Firma zusätzliches Geld
  • Die Firma profitiert von meiner verbesserten Qualifikation
  • Ich habe meine Leistung und meine Verantwortung ausgebaut

 

Weitere Aussagen, die ich hier sinngemäß oder gar wörtliche wiedergeben will:

  • Jeder Chef weiß: Spitzenmitarbeiter müssen auch Spitzengehälter bekommen
  • Gerade Besserverdiener sind in der Krise wichtiger denn je
  • Selbst-PR: Erfolg hängt zu 10 Prozent von der Leistung ab – und zu 90 Prozent davon, wie man diese Leistung verkauft
  • Ein Lob durch Dritte ist besonders wirksam
  • Dass die Vergütung mit den Dienstjahren wächst, dieses Prinzip gilt nur bei Beamten. Der Staat ist nicht umsonst pleite
  • Klammern Sie Ihren persönlichen Vorteil aus. Zeigen Sie, was die Firma davon hat

 

Als Vorgesetzter finde ich einen Punkt noch ganz besonders heikel: Das Thema Überstunden. Darauf bin ich bereits in meinem letzten Blogeintrag eingegangen, allerdings will ich es nochmal aufgreifen: Man macht sich keinen Gefallen damit, wenn man dies als Mitarbeiter ins Gespräch einbringt. Wenn ich als Vorgesetzter z.B. eine minutiöse Auflistung von Überstunden bekommen würde, dann müsste ich mich fragen, ob mein Mitarbeiter die Arbeit derartig hasst, dass er sich tatsächlich jede Stunde aufschreiben muss. Außerdem gilt wie bei Stempeluhren, die von vielen Vorgesetzten für gut befunden werden, das Argument: Das sagt mir, dass der Mitarbeiter da war, aber nicht ob und was er geleistet hat. Vielleicht (!) ist die Mehrarbeit auch ein Indikator dafür, dass der Angestellte eine zu niedrige Arbeitsleistung hat. Darüber hinaus haben Vorgesetzte oftmals ein deutlich höheres Kontingent an Überstunden, was ggf. zum Streit über Überstunden ausarten könnte. Des Weiteren ist es meinem persönlichen Verständnis nach so, dass in der IT Branche fünf “Überstunden” die Norm und nicht die Ausnahme sind. Wenn man damit nicht leben kann, sollte man sich über einen anderen Beruf Gedanken machen. Zu guter Letzt ist es dann auch noch so, dass der Vorgesetzte diese Überstunden nicht prüfen kann (noch will, noch sollte). Schließlich ist man erfahrungsgemäß während der Arbeitszeit auch mal privat im Netz unterwegs oder telefoniert, sodass mir die komplette Thematik zu wischi waschi ist. Und vergesst eines nicht: Überstunden zeigen ihre Auswirkung hoffentlich in Form von besseren Ergebnissen. Diese wiederum kann man sehr gut als Argument einbringen!

RTL Explosiv versteht Social Media nicht

„Wenn Unrecht zu Recht wird, wird Widerstand zur Pflicht!“ – Bertolt Brecht

Das haben sich heute wohl viele aus der Social Media Community gedacht, denn aus einem Beitrag von RTL Explosiv über Besucher der gamescom Köln entwickelte sich ein regelrechtes Facebook Lauffeuer. Auf die Diskussion über das Thema des Beitrags und wie dieses vermittelt wird, will ich allerdings nicht eingehen, stattdessen geht es mir (v.a. als Social Media Manager bei uns im Unternehmen) um die Art und Weise wie RTL Explosiv bzw. die Verantwortlichen der Fan Page mit der Kritik in Form von Kommentaren umgegangen sind.

Ganz simpel ausgedrückt: Die Reaktion deckte so ziemlich alles ab, was man niemals tun sollte! Nicht erwünschte respektive negative Kommentare wurden einfach gelöscht. Eine meiner Arbeitskolleginnen wurde – zumindest hat es so den Anschein – von weiteren Beiträgen ausgeschlossen (Anm.: Ihr Kommentar rechtfertigt das in keiner Weise!). Eine offizielle Stellungnahme vermissen ich und vermutlich viele weitere bis jetzt noch. Lediglich der Reporter Tim Kickbusch, der an dem Beitrag beteiligt war, entschuldigte sich in seinem persönlichen Profil und beteuerte, dass er niemanden lächerlich machen wollte.

 

image_thumb[4]

 

Während des Verfassens dieses Blogeintrags hat er allerdings inzwischen auch seine Pinnwand vor öffentlichem Zugriff gesperrt. Meine Kollegin kommentierte das wie folgt: “Tja, findet er es wohl doch nicht mehr so witzig”.

Ein weiterer Blick just in diesem Moment brachte weitere Informationen zu Tage:

 

image_thumb[8]

 

Überrascht bin ich von der schnellen, koordinierten und geschlossenen Reaktion nicht – Ganz im Gegenteil! Ich lege den Verantwortlichen dringend nahe, dass sie sich näher mit Social Media Guidelines bzw. allgemein mit der Community im Netz befassen. Viele Regeln, wie sie vielleicht abseits des Internets existieren, gelten hier nicht mehr – und das zu Recht! Ehrlichkeit, Transparenz, Offenheit und nicht zuletzt das Zuhören und Zugeben von Fehlern haben für uns – die Community – höchsten Stellenwert. Charaktereigenschaften, die im realen Leben vielleicht schon auf der Strecke geblieben sind…

 

Verabschieden will ich mit den Worten: "Offenheit verdient immer Anerkennung." – Otto von Bismarck

Data Annotations für valide DTOs

Wer viel mit DTOs arbeitet, der sollte sich in jedem Fall Data Annotations aus dem .NET Framework anschauen. Ich habe diese kürzlich wieder für ein DTO zur Speicherung der Database Configuration verwendet. Das DTO sieht wie folgt aus:

   1: public abstract class DatabaseConfig

   2: {

3: [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Bitte den

Instanznamen der Datenbank angeben.")]

   4:     public string InstanceName { get; set; }

   5:  

6: [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Bitte den

Datenbanknamen angeben.")]

   7:     public string DatabaseName { get; set; }

   8:  

   9:     public string UserName { get; set; }

  10:  

  11:     public string Password { get; set; }

  12:  

13: [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Bitte die

Einstellung für IntegratedSecurity setzen.")]

  14:     public bool IntegratedSecurity { get; set; }

  15: }

 

Dabei handelt es sich nur um ein sehr einfach Beispiel. Es ist problemlos auch möglich Ranges für Zahlen anzugeben, String-Längen zu definieren oder gar ganz eigene Annotations zu bauen, um z.B. Emailadressen zu validieren.

Was jetzt noch fehlt ist eine Implementierung eines Validator. Ich habe das Interface wie folgt definiert:

   1: public interface IValidator<in TIn>

   2: {

   3:     /// <summary>

   4:     /// Liefert die Fehlermeldungen zu allen ungültigen Werden als String zurück

   5:     /// </summary>

   6:     /// <param name="input"></param>

   7:     /// <returns></returns>

   8:     string ToString(TIn input);

   9:  

  10:     /// <summary>

  11:     /// Liefert eine Auflistung aller ungültigen Werte

  12:     /// </summary>

  13:     /// <param name="input"></param>

  14:     /// <returns></returns>

  15:     ICollection<string> GetMessages(TIn input);

  16:  

  17:     /// <summary>

  18:     /// Prüft, ob das zu validierende Objekt gültig ist

  19:     /// </summary>

  20:     /// <param name="input">Das zu validierende Objekt</param>

  21:     /// <returns>true, wenn valide</returns>

  22:     bool IsValid(TIn input);

  23: }

 

Die Implementierung speziell für die Validierung von Data Annotations (das Interface lässt sich schließlich auch noch für andere Validierungen verwenden) sieht so aus:

   1: public class DataAnnotationsValidator<TIn> : IValidator<TIn>

   2: {

   3:     public string ToString(TIn input)

   4:     {

   5:         var invalidProperties = new StringBuilder();

   6:         foreach (var errorMessage in GetErrors(input))

   7:         {

   8:             invalidProperties.AppendLine(errorMessage);

   9:         }

  10:  

  11:         return invalidProperties.ToString();

  12:     }

  13:  

  14:     public ICollection<string> GetMessages(TIn input)

  15:     {

  16:         return GetErrors(input).ToList();

  17:     }

  18:  

  19:     public bool IsValid(TIn instance)

  20:     {

  21:         var invalidProperties = from prop in typeof (TIn).GetProperties()

22: from attribute in prop.GetCustomAttributes(false).

OfType<ValidationAttribute>()

  23:                                 where !attribute.IsValid(prop.GetValue(instance, null))

  24:                                 select attribute;

  25:  

  26:         return invalidProperties.Count() == 0;

  27:     }

  28:  

  29:     private static IEnumerable<string> GetErrors(TIn instance)

  30:     {

  31:         return from prop in typeof(TIn).GetProperties()

  32:                from attribute in prop.GetCustomAttributes(false).OfType<ValidationAttribute>()

  33:                where !attribute.IsValid(prop.GetValue(instance, null))

  34:                select attribute.FormatErrorMessage(prop.Name);

  35:     }

  36: }

 

Und schon in der Bibel steht geschrieben: Entwickle testgetrieben. Deswegen noch zum Abschluss meine Specs (alles in eine Klasse mit dem Namen DataAnnotationsValidatorSpecs.cs einfügen), geschrieben mit dem Framework Machine.Specifications (gibt es auch als NuGet-Package: install-package Machine.Specifications):

   1: public class DataAnnotationsValidatorTestBase

   2: {

   3:     protected static DtoTestClass Config = new DtoTestClass();

   4:  

   5:     public class DtoTestClass

   6:     {

7: [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Bitte den

Datenbanknamen angeben.")]

   8:         public string Database { get; set; }

   9:         public string Server { get; set; }

  10:         public string User { get; set; }

  11:     }

  12: }

  13:  

  14: public class When_an_invalid_object_is_passed : DataAnnotationsValidatorTestBase

  15: {

  16:     Establish context = () =>

  17:     {

  18:         _validator = new DataAnnotationsValidator<DtoTestClass>();

  19:         Config.Database = string.Empty;

  20:  

  21:     };

  22:  

  23:     private Because of = () => _isValid = _validator.IsValid(Config);

  24:  

  25:     private It should_evaluate_it_as_invalid = () => _isValid.ShouldBeFalse();

  26:  

  27:     private static DataAnnotationsValidator<DtoTestClass> _validator;

  28:     private static bool _isValid = true;

  29: }

  30:  

  31: public class When_an_valid_object_is_passed : DataAnnotationsValidatorTestBase

  32: {

  33:     Establish context = () =>

  34:     {

  35:         _validator = new DataAnnotationsValidator<DtoTestClass>();

  36:         Config.Database = "bac";

  37:  

  38:     };

  39:  

  40:     private Because of = () => _isValid = _validator.IsValid(Config);

  41:  

  42:     private It should_evaluate_it_as_valid = () => _isValid.ShouldBeTrue();

  43:  

  44:     private static DataAnnotationsValidator<DtoTestClass> _validator;

  45:     private static bool _isValid = false;

  46: }

  47:  

  48: public class When_an_object_has_no_annotations

  49: {

  50:     internal class test

  51:     {

  52:  

  53:     }

  54:  

  55:     Establish context = () =>

  56:     {

  57:         _validator = new DataAnnotationsValidator<test>();

  58:  

  59:     };

  60:  

  61:     private Because of = () => _isValid = _validator.IsValid(new test());

  62:  

  63:     private It should_evaluate_it_as_valid = () => _isValid.ShouldBeTrue();

  64:  

  65:     private static DataAnnotationsValidator<test> _validator;

  66:     private static bool _isValid = false;

  67: }

  68:  

69: public class When_an_object_with_one_invalid_property_is_passed :

DataAnnotationsValidatorTestBase

  70: {

  71:     Establish context = () =>

  72:     {

  73:         _validator = new DataAnnotationsValidator<DtoTestClass>();

  74:         Config.Database = string.Empty;

  75:  

  76:     };

  77:  

  78:     private Because of = () => _messages = _validator.GetMessages(Config);

  79:  

  80:     private It should_evaluate_exactly_this_property_as_invalid = () =>

  81:     {

  82:         (_messages.Count == 1).ShouldBeTrue();

  83:         _messages.Aggregate(string.Empty, (current, message) => current + message)

  84:             .Contains("Datenbanknamen").ShouldBeTrue();

  85:     };

  86:  

  87:     private static DataAnnotationsValidator<DtoTestClass> _validator;

  88:     private static ICollection<string> _messages;

  89: }

T-SQL Abfrage für Tags

Gerade musste ich eine etwas schwierigere Auswertung machen. Die Aufgabenstellung dazu war:

“Ermittle alle Kunden, die weder der Branche Handel noch Verbraucher zugeordnet sind.”

Nun muss man wissen, dass wir die Branchen an einem Kunden quasi wie Tags haften. Im ERP sieht das so aus:

image

Dementsprechend gibt es zw. der Tabelle Kunde und Branche eine n:m Beziehung. Ein Kunde kann keinen Tag, nur einen oder mehrere haben. Ein Tag kann wiederum keinem Kunden, genau einem oder mehreren zugeordnet sein. Gemäß der Normalisierungsregeln für relationale Datenbanken ist die Tabelle Branchen so aufgebaut, dass z.B. für das oben genannte Beispiel 4 Einträge zu dem Kunden mit der ID 7001 drin stehen. Pro Tag jeweils einen Eintrag.

Das schwierige war nun, dass ich den kompletten Kundenstamm durchlaufen und für jeden gefundenen Kunden eine Unterabfrage feuern musste, die prüft, ob in irgendeinem der zugeordneten Tags der Begriff Handel oder Verbraucher vorkommt. Im Programmcode wäre das eine klassische For Each Schleife, welche im inneren nochmal eine For Each Schleife enthält (Anmerkung: Wenn man sich mit LINQ auskennt, geht es auch einfacherSmiley).

Wie macht man das nun mit T-SQL am einfachsten, wenn man zu faul ist zum Programmieren? Nachdem ich mich mit dem Wissensvermittler meines Vertrauens (Google) beraten habe, war die eleganteste und einfachste Lösung das Verwenden des Befehls

For XML Path(“)

Ein konkretes Beispiel findet ihr hier :

SELECT p1.CategoryId,
     
( SELECT ProductName + ‚,‘
          FROM Northwind.dbo.Products p2
         WHERE p2.CategoryId = p1.CategoryId
         ORDER BY ProductName
           FOR XML PATH(“) ) AS Products

  FROM Northwind.dbo.Products p1
GROUP BY CategoryId ;

In der erzeugten Spalte steht dann der XML String. Bei uns sah das so aus:

<Beschreibung>Maschinenbau </Beschreibung><Beschreibung>Anlagenbau/ Apparatebau</Beschreibung>

Nun konnte ich mit LIKE prüfen, ob in diesem z.B. Handel oder Verbraucher steht.

Ausschreibung für Diplomstellen

Ich suche für unsere IT Abteilung noch Diplomanden zu den unterschiedlichsten IT Themen. Neben diversen Vorschlägen meinerseits, die ihr unter http://goo.gl/Ij58U findet, könnt ihr auch gerne selbst welche für die Bereiche

  • Softwareentwicklung mit .NET
  • Webentwicklung für unser CMS Typo3 mit PHP5
  • System- und Netzwerkadministration
  • Marketing / Public Relations

einreichen. Speziell im Umfeld des Web und Marketings sind SEO und Social Media Themen für uns von besonderem Interesse.

Wir bieten flexible Arbeitszeiten, eine adäquate Vergütung, sehr gut ausgerüstete Arbeitsplätze, neuste Technologien und Software, ein super Arbeitsklima und ein junges, hochmotiviertes IT Team. Eine anschließende Festanstellung ist denkbar. Ihr könnt alle IT-ler per Email, Telefon, Xing oder auch Facebook erreichen. Die Profile dazu findet ihr über unsere Fanpage https://www.facebook.com/hecogmbh, indem ihr nach den Namen von uns sucht. Martin Edelmann dürfte in diesem Fall der beste Ansprechpartner sein, da er vor 2 Jahren ebenfalls seine Diplomarbeit bei uns gemacht hat.

Wer aus Karlsruhe kommt, kann sich der IT Fahrgemeinschaft anschließen. In Remchingen-Nöttingen ist man von Karlsruhe mit dem Auto in ca. 20 Minuten. Mit der Bahn kommt man vom Durlacher Tor in unseren Nachbarort Wilferdingen ebenfalls in 20 Minuten (Verzögerungen durch die Baustellensituation nicht eingerechnet).

Facebook Fanpage – Einträge mit dem eigenen Namen

Wer eine Fanpage in Facebook für seine Firma als Administrator verwaltet, der schreibt per Standardeinstellung im Namen der Firma, auch wenn er mit seinem eigenen Profil angemeldet ist. Ich bin bei der Firma heco beispielsweise als Administrator der Fanpage angelegt. Wenn ich auf die Pinnwand schreibe oder Fotos kommentiere, dann zeigt es statt meinem Namen immer den Namen der Firma an.

Das ist nicht immer gewünscht. Abstellen kann man dies, indem man auf die Fanpage wechselt und dann rechts oben auf “Seite bearbeiten” klickt. Auf der Folgeseite klickt ihr dann links auf “Deine Einstellungen”. Nun könnt ihr in der Mitte den Haken setzen: “Kommentiere und poste Beiträge auf deiner Seite immer unter dem Namen (Fanpage Name), auch wenn du Facebook als (euer Profilname) verwendest.”

 

clip_image002

%d Bloggern gefällt das: