Februar « 2013 « Bernhard Krenz

Archive for Februar, 2013

Offene Verbindungen zu einer SQL-Datenbank trennen

Ab und zu steht man vor der Herausforderung eine SQL-Datenbank wiederherzustellen oder sonstwie zurück zu setzen. Dann wird man schnell mit dem Problem konfrontiert, dass offene Verbindung zur Datenbank diese Aufgabe verhindern.

Nun kann man entweder mit den üblichen Tools, wie dem SQL-Management-Studio, die Verbindungen trennen, oder man bastelt sich dazu ein kleines Skript. Da ich selber hauptsächlich skriptbasiert arbeite, habe ich dafür folgenden Algorithmus entwickelt:

USE master

DECLARE @databaseName VARCHAR(15)
SET @databaseName = 'name_of_your_database'

DECLARE @kill_id INT
DECLARE @disconnectQuery NVARCHAR(255)
DECLARE killprocess_cursor CURSOR FOR SELECT a.spid FROM sysprocesses a JOIN sysdatabases b ON a.dbid = b.dbid WHERE b.name = @databaseName
OPEN killprocess_cursor

FETCH NEXT FROM killprocess_cursor INTO @kill_id
WHILE @@FETCH_STATUS = 0
BEGIN
	SET @disconnectQuery = 'KILL '+ CONVERT(VARCHAR, @kill_id)
	RAISERROR ('EXECUTING: %s', 1, 1, @disconnectQuery) WITH NOWAIT
	EXEC (@disconnectQuery)
	FETCH NEXT FROM killprocess_cursor INTO @kill_id
END	

CLOSE killprocess_cursor
DEALLOCATE killprocess_cursor

Das Skript durchläuft mit einem Cursor sämtliche offenen Prozesse der festgelegten Datenbank und schließt diese mit Hilfe des „Kill“-Befehls und der zugehörigen Prozess-Id.


if (![nil isEqualToString:nil]) { }

Das folgende Verhalten entspricht der Apple’s Objective-C 2.0 Dokumentation, ist aber möglicherweise nicht jedermann bekannt.

Bei einem Vergleich zweiter Strings in iOS mit isEqualToString, wird das „do something“ im folgenden Codeschnipsel auch ausgeführt, wenn beide Argumente nil sind, obwohl diese auf den ersten Blick gleich erscheinen.

if (![string1 isEqualToString:string2])
{
 // do something
}

Das liegt daran, dass eine Methode zu nil immer 0 zurückgibt und als false interpretiert wird. Die if-Bedingung ist damit erfüllt.

Die korrekt Art und Weise das obere Beispiel umzusetzen, wäre also:

if (![string1 isEqualToString:string2] && (string1 != nil || string2 != nil))
{
  // do something
}

Dateiupload mit Windows-Phone 8

Wer versuch mit der API von Windows-Phone (7, 7.5, 8) eine Datei auf einem Webserver hochzuladen, wird schnell merken, dass die einfach zu nutzende WebClient-Klasse hierfür keine Funktionen zur Verfügung stellt.

Wer keine Lust hat in den Tiefen des HttpWebRequest zu irren, der nutzt dazu am Besten vorhandene Bibliotheken der Community. Ein Dateiupload lässt sich zum Beispiel mit RestSharp realisieren.

In meinem Beispiel will ich eine Datei aus einem bestimmten Verzeichnis des IsolatedStorage hochladen.

Schritt 1: Ermittlung des Dateipfades

var directoryName = "FilesToUpload";

string[] files = null;

// get all files from the isolatedstorage in the specified directory
using (var storage = IsolatedStorageFile.GetUserStoreForApplication())
{
	// if the directory does not exists, there is nothing to do
	if (!storage.DirectoryExists(directoryName))
	{
		return;
	}

	files = storage.GetFileNames(Path.Combine(directoryName, "*.xml"));
}

// if there is no file present in the directory,
// there is nothing to do either
if (files == null || files.Length == 0)
{
	return;
}

// use the first file for upload
var filePath = Path.Combine(directoryName, files[0]);

Schritt 2: Formulierung des Webrequests

(continue reading…)


Falsche Größe eines ImageView in einem ListView

Wer in einem Android-ListView Reihen mit unterschiedlicher Höhe hat, zum Beispiel Bilder und Text-Elemente, wird eventuell wie ich auf das Problem stoßen, dass die Reihe für das Bild mit einer falschen Höhe angezeigt wird.

In meinem Fall war diese zu hoch, was je nach Skalierungsverhalten des Bildes entweder zu einer Verzerrung des Bildes oder zu einem Abstand zur nächsten Reihe führte.

Im Adapter des ListViews muss deshalb zur Laufzeit die Höhe des Bildes berechnet und manuell gesetzt werden. Der View dazu wird aus einer Layout-XML in res/layout erzeugt.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical">

	<ImageView
		android:id="@+id/imageView"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:scaleType="fitXY"
		/>

</LinearLayout>

Die getView-Methode im Adapter könnte wie folgt aussehen. Dies ist natürlich nur der Auszug für den ImageView. Für die anderen Reihen gibt es je nach Position anderen Inhalt.

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
	View view = (LinearLayout) mInflater.inflate(R.layout.image_item, null);
	
	ImageView imageView = (ImageView) view.findViewById(R.id.imageView);

	// load the bitmap for the image source
	String filePath = "xyz"; // you get this from somewhere, depending on the position	
	Bitmap bitmap = Util.loadBitmap((Activity) context, RessourceLoader.getFilesDirectory() + filePath);
	
	if (bitmap != null)
	{
		imageView.setImageBitmap(bitmap);

		// get the dimensions of the current display
		DisplayMetrics dm = new DisplayMetrics();
		((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
		if (dm != null)
		{
			// calculate height and set it via layout params
			float height = ((float) dm.widthPixels / bitmap.getWidth()) * bitmap.getHeight();
			imageView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)height));
		}
	}
	
	return view;
}

SQL-Skriptdateien aus Masterskript aufrufen

Bei der Architektur einer Datenbank gilt es nach einer Testphase oder nach Änderungen oftmals diese komplett neu aus den beteiligten Skripten zu erzeugen. Um zu viel manuelle Arbeit zu vermeiden erzeuge ich mir dazu ein weiteres Skript, welches neben der Installation der Datenbank auch alle beteiligten Skripte in fest definierter Reihenfolge ausführt.

Das Ausführen der Skripte aus aus einer Datei erfolgt über den Befehl xp_cmdshell. Dieser macht nichts weiter, als einen Befehl an die Windows-Kommandozeile weiter zu erreichen. Der Befehl ist im Standardfall allerdings sicherheitsbeschränkt, weshalb die Konfiguration vorher geändert werden muss.

Folgende Schritte sind dazu notwendig:

  1. Löschen der Datenbank falls diese existiert
  2. Datenbank neu erstellen
  3. Berechtigung konfigurieren, um Skripte aus Dateien auszuführen
  4. Konstanten deklarieren und initialisieren
  5. Skript-Dateien in eine temporäre Tabelle einfügen
  6. Diese Tabelle in einer Schleife durchlaufen und die Skripte aus den Dateien ausführen

Sehen wir uns einige der Schritte im Detail an:

Schritt 3:

-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1

GO

-- To update the currently configured value for advanced options.
RECONFIGURE

GO

-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1

GO

-- To update the currently configured value for this feature.
RECONFIGURE

Mit diesem Schnipsel werden die erweiterten Berechtigungen für den xp_cmdshell-Befehl gesetzt.

(continue reading…)


Instanz aus Klassennamen erzeugen

Nehmen wir folgenden Fall an: Der Name einer Klasse liegt als string vor und es gilt eine Instanz der Klasse zu erzeugen.

Das kann zum Beispiel so funktionieren:

// you got the name of the class from somewhere
string className = "Message";
// create the type of the class using the destinated namespace
var type = Type.GetType("ValueObjects." + className, false); 
// create the instance now
var message = Activator.CreateInstance(type) as Message;

In ASP.Net funktioniert das allerdings nicht. Hier ist ein Workarund über den BuildManager (using System.Web.Compilation) notwendig:

// you got the name of the class from somewhere
string className = "Message";
// create the type of the class using the destinated namespace
var type = BuildManager.GetType("ValueObjects." + className, false);
// create the instance now
var message = Activator.CreateInstance(type) as Message;

Existiert eine Konstante?

Wer regelmäßig mit iOS arbeitet wird schnell einmal mit dem Problem konfrontiert, dass eine zu verwendende System-Konstante nur in einer neueren iOS-Version verfügbar ist.

Hier stellt sich die Frage, wie zu prüfen ist, ob die Konstante in der iOS-Version des Nutzers überhaupt zur Verfügung steht, um durch eine geeignete Weiche Abstürze zu vermeiden.

Das Ganze zeige ich am Beispiel einer Observer-Konstante des MPMoviePlayerControllers zum Abspielen von Videos, welche einem die Möglichkeit bietet, ein Video erst dann einzublenden, wenn das erste Frame zur Verfügung steht. Denn nur so kann man ein Flickern am Anfang des Videos vermeiden:

if (&MPMoviePlayerReadyForDisplayDidChangeNotification != NULL) // check if constant exists
{
	// >= iOS 6.0, use readyForDisplay property
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoIsVisibleChanged:) name:MPMoviePlayerReadyForDisplayDidChangeNotification object:nil];
}
else
{
	// < iOS 6.0, use playbackState property
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoStateChanged:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
}

Copyright © 2012-2019 Bernhard Krenz Alle Rechte vorbehalten.