Solving development problems  |  About this blog

Archive for the ‘database’ tag

Adding stored JavaScript procedures to MongoDB using Windows Batch script

MongoDB can use stored procedures similar to MSSQL. To make a MongoDB procedure create a new file, name it like DoSomething.js, write a function and attach it to database.

Guide through example

Lets say we have a log of website visitors stored in visitors collection inside myweb database. Each visitors record contains date and time of a visit. Now we want to create monthly statistics – how many users visits website per month.

visitors collection looks like:

> use myweb
> db.visitors.findOne()
{
  "_id": ObjectId("4e0cb7e7da3ea11d18d841e7"),
  "timestamp": "Thu Jun 30 2011 19:52:39 GMT+0200 (Central Europe Daylight Time)"
}

Most reusable way to get data is to create a stored procedure GetVisitsPerMonth() and call it on demand. Create a file GetVisitsPerMonth.js and copy-paste the following code inside. Note that file name is named by procedure.

function ()
{
	var result = db.visitors.group(
	{
		keyf: function(doc)
		{
			return { //NOTE: Bracket must be in this line!!!
				month: doc.timestamp.getMonth(),
				year: doc.timestamp.getFullYear()
			};
		},
		initial: {count:0},
		reduce: function(doc, prev) { prev.count++ }
	});

	return result;
}

How to attach one procedure

Stored procedure can be manually attached like this:

db = connect("localhost:27017/myweb");
db.system.js.save({"_id":"GetVisitsPerMonth", "value": function() { ... });

How to attach multiple procedures

Large sets of procedures should be well organized in files so you can quickly find a procedure and fix it if necessary. To insert or update all procedures at once use a simple batch script.

Create a new file, name it install.bat and copy-paste the following code inside:

@echo off

:parameters
set DBCON=localhost:27017/myweb
set MONGO=c:\mongodb\bin\mongo.exe
set SCRIPT=script.js

:startup
if not exist %MONGO% goto error
if not "%1"=="" goto add

rem Append connection string
echo Adding connection string...
echo db = connect("%DBCON%"); > %SCRIPT%
echo. >> %SCRIPT%

rem Append scripts
call %0 GetVisitsPerMonth
rem call %0 DoSomething
rem other procedures go here

goto install
rem goto end

:add
echo Adding script %1...
echo db.system.js.save({"_id":"%1", "value": >> %SCRIPT%
type %1.js >> %SCRIPT%
echo }); >> %SCRIPT%
echo. >> %SCRIPT%
goto end

:install
echo Running script...
%MONGO% %SCRIPT%
goto end

:error
echo Check if mongo is installed:
echo %MONGO%

:end

Edit parameters according to your needs: path to mongo.exe, database name, and list of procedures.
Simply run the script and it is done.

Testing a stored procedure

Log into mongo console:

> use myweb
> db.eval("GetVisitsPerMonth()")
[
  {
    "month": 5,
    "year": 2011,
    "count": 28233,
  },
  {
    "month": 6,
    "year": 2011,
    "count": 48026,
  },
  {
    "month": 7,
    "year": 2011,
    "count": 92754,
  }
]

Written by developer

October 7th, 2011 at 1:05 pm

LINQ Max and Min functions upgraded

Classic LINQ Max and Min functions have the same problem as First function – exception can occur, so we use FirstOrDefault which returns null instead of exception.

So, this is how you can extend Min and Max functions into MinOrDefault and MaxOrDefault;

public static class IEnumerableExtensions
{
  public static int MinOrDefault(this IEnumerable source,
    Func selector, int defaultValue)
  {
    if (source.Any())
      return source.Min(selector);

    return defaultValue;
  }

  public static int MaxOrDefault(this IEnumerable source,
    Func selector, int defaultValue)
  {
    if (source.Any())
      return source.Max(selector);

    return defaultValue;
  }
}

 

Usage example:

  YourDataContext db = new YourDataContext();
  int maxVisits = db.SomeEntityTables.MaxOrDefault(x => x.SomeFieldYouSearchForMaximum, 0);

How to clear recent servers list in MS SQL 2005 Management Studio?

So, you have Microsoft SQL Server 2005 Management Studio (SSMS) and when trying to connect “Server name” drop down list is filled with sensitive data:

To clear this list, all you have to do is delete this file:
C:\Documents and Settings\<user>\Application Data\Microsoft\Microsoft SQL Server\90\Tools\Shell\mru.dat.

Just remember, once you delete that file all of your previous connections will be lost. So make sure that you have any necessary IP addresses, usernames, and passwords that you’ll need to reconnect to your favorite/most used SQL Servers.

Create Linq to SQL classes from .sdf (Local database)

Linq allows to handle data easily. Linq to SQL tools are integrated in Visual Studio but is limited to can generate code only for  certain databases. To create ORM from .sdf database file read on…

What to do?
Copy next script to a file with .bat extension.

Change DATABASE_NAME, DATABASE_PASSWORD and NAMESPACE according to your needs.

@echo off
rem Input parameters
rem DATABASE_NAME should NOT contain spaces
set DATABASE_NAME=MyDatabase
set DATABASE_PASSWORD=mypass
set NAMESPACE=MyNamespace.Database

rem Set full path to SqlMetal.exe
rem For 64-bit Windows
set SQLMETAL="%ProgramW6432%\Microsoft SDKs\Windows\v6.0A\Bin\SqlMetal.exe"
rem For 32-bit Windows
if "%ProgramW6432%"=="" set SQLMETAL="%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\Bin\SqlMetal.exe"

rem Other parameters
set DATABASE_PATH="%CD%\%DATABASE_NAME%.sdf"
set OUTPUT_CS_PATH="%CD%\%DATABASE_NAME%.cs"
set OUTPUT_DBML_PATH="%CD%\%DATABASE_NAME%.dbml"
set CONNECTION_STRING="Data Source=\"%DATABASE_PATH%\"; Password=\"%DATABASE_PASSWORD%\";"

rem Check and run sqlmetal
if not exist %SQLMETAL% goto error-missing-sqlmetal
%SQLMETAL% /conn:%CONNECTION_STRING% /dbml:%OUTPUT_DBML_PATH% /namespace:%NAMESPACE% /context:%DATABASE_NAME%DataContext /pluralize
%SQLMETAL% /conn:%CONNECTION_STRING% /code:%OUTPUT_CS_PATH% /namespace:%NAMESPACE% /context:%DATABASE_NAME%DataContext /pluralize
goto end

:error-missing-sqlmetal
echo Error: cannot find sqlmetal.exe
echo Search location: %SQLMETAL%
goto end

:end

Example

If the database is stored in C:\db\Website.sdf then copy script into C:\db\make.bat. Change DATABASE_NAME to Website and run the script. Script should generate C:\db\Website.cs and C:\db\Website.dbml files. Include the generated .cs file into your project.

Using the generated code

class Program
{
  static void Main()
  {
    //Suppose that Website.sdf has Page table with CreationDate column of type DateTime
    WebsiteDataContext db = new WebsiteDataContext(@"C:\db\Website.sdf");
    var list = from p in db.Pages
                 where p.CreationDate > DateTime.Today
                 selet p;

    //Show number of pages that match Linq query
    Console.WriteLine(list.Count() + " pages created today.");
  }
}

Written by developer

March 30th, 2010 at 7:53 pm

Posted in Projects

Tagged with , , , , , , ,

Saving Changes is Not Permitted?

We tried to add new ntext nullable column in MS SQL table.  We were quite surprised to get the following error message:

image

Saving changes is not permitted.  The changes you have made require the following tables to be dropped and re-created.  You have either made changes to a table that can’t be re-created or enabled the option Prevent saving changes that require the table to be re-created.

It wouldn’t let us add an “Allow Nulls” column?  That just seemed absurd.

Apparently, this is now the default behavior for any of the following changes to a table:

  • Adding a new column to the middle of the table
  • Dropping a column
  • Changing column nullability
  • Changing the order of the columns
  • Changing the data type of a column

In order to prevent this default behavior, you simply need to uncheck a box in the table designer options using the Tools -> Options menu item

image

Expand the Designers section to display the Table and Database Designers options.

image

To change this behavior, just uncheck the “Prevent saving changes that require table re-creation” checkbox.

Original article was published at http://codeslammer.wordpress.com/2008/10/19/saving-changes-is-not-permitted/

Written by developer

December 21st, 2009 at 4:44 pm