Archive for the ‘SQL Server 2008’ Category

No columns when binding to complex type in Entity Framework

The day before yesterday I had my problem with getting my stored proc recognised in the Entity Framework (EF) designer in Visual Studio 2010 (VS2010). Yesterday my next step was to get one of my stored procedures (sprocs) that use Full Text Search (FTS) bound to a complex type. So I could get all the results and aggregations in one round trip to the database. I started with the simplest sproc I could:

CREATE PROCEDURE [dbo].[P_ParentFullTextSearch]
@queryString NVARCHAR(250)
AS
BEGIN
SELECT P.[ID], P.[Name],
(SELECT COUNT(1)
FROM  dbo.[Children] C
WHERE P.[ID] = [C.ParentID]) AS ChildrenCount
FROM   dbo.[Parent] P
WHERE  FREETEXT(P.[Name], @queryString)
AND    P.IsDeleted = 0
END

I granted EXECUTE and CONTROL permissions to the EF connection string SQL Server login on the proc and could get it picked up in the Add Function Import but could not retrieve any column information. Frustrating…

I tried a number of things on the MSDN forums like SET NOCOUNT OFF and adding the VIEW DEFINITION permission. None worked. After running a trace (the first thing I should have done) in the SQL Server Profiler I found clicking Get Column Information was executing:


SET FMTONLY OFF;
SET FMTONLY ON;
EXEC [db_name].[dbo].P_ParentFullTextSearch @queryString=null;
SET FMTONLY OFF;

The problem comes from the fact you CANNOT use nulls in FTS predicates – DOH should have noticed that. This causes the metadata query to fall over. Unfortunately the error you get when running the SQL does not bubble up into the Add Function Import window.

A simple NULL check resolved the issue:

CREATE PROCEDURE [dbo].[P_ParentFullTextSearch]
@queryString NVARCHAR(250)
AS
BEGIN
IF @queryString IS NULL
BEGIN
SELECT    (CAST NULL AS INT) AS [ID],
(CAST NULL AS NVARCHAR(50)) AS [Name],
(CAST NULL AS INT) AS [ChildrenCount]
RETURN
END
SELECT P.[ID], P.[Name],
(SELECT COUNT(1)
FROM dbo.[Children] C
WHERE P.[ID] = [C.ParentID]) AS ChildrenCount
FROM dbo.[Parent] P
WHERE FREETEXT(P.[Name], @queryString)
AND P.IsDeleted = 0
END

Behold! Metadata and a sproc bound to a complex type.

Cannot see stored procedure in Entity Framework model?

Unfortunately I could not see the stored procedure in the list of items to be added when refreshing the model from the database. I have been implementing a stored procedure/inline-table function to facilitate a Full Text Search (FTS) in SQL Server 2008 using ADO .NET Entity Framework (EF).

The cause was that the EF connection did not have Control/Execute permissions on the function/procedure. Grant these permissions to the user utilised in your EF connection string and it will pop-up in the list of stored procedures to be added when you go back to update the model.

Once that is done you can then map the proedure/function results to your entities or a complex type. This is accomplished by selecting Add function import when right-clicking anywhere in the EDMX Designer View or the stored procedure in the Model View.

AdoMdClient – Where are the measure groups?

Been busy creating a Silverlight/SSAS mashup recently to show off their potential when used together to both colleagues and clients. While attempting to build the measure selection/filtering interface I thought it would be pleasant if they were grouped by their… measure groups, hierarchically like they are when browsing a cube in SSMS or Visual Studio. Measures are easy enough to find as a collection on the CubeDef object as a MeasureCollection. But where are measure groups hiding?

Naturally I would have thought there would be a MeasureGroup or MeasureGroupCollection off the CubeDef – no such luck. Debugging and taking a closer look at the Measure object, in the PropertyCollection (the Properties member) I spyed the property MEASUREGROUP_NAME. The sweet smell of victory. So to get your measure’s measure group here is the C#:

Property measureGroupProperty = measure.Properties["MEASUREGROUP_NAME"];
string measureGroupName = measureGroupProperty.Value.ToString();

The GETDATE() of MDX

I have been repeatedly asked to produce queries in MDX across a number of SSAS cubes that use the query execution date/time and I have reused this little gem repeatedly:

StrToMember("[Date].[Date].[" + Format(now(), "yyyyMMdd" + "]")


Here it is in a complete query that returns a measure over the last 4 days from the time of execution:

SELECT
    [Measures].[Menace]
ON COLUMNS,
    LastPeriods(4,
        StrToMember("[Date].[Date].[" + Format(now(), "dd-MM-yyyy") + "]")
    )
ON ROWS
FROM [CubeOfDoom]


MDX has no GETDATE() function to obtain the member associated with the current date/time as it is up to each implementation how the date/time dimension is populated and how its members are named. If you populate your date/time dimension up to the time period of execution you can make use of DefaultMember or CurrentMember but what if the way the dimension is populated has to change in the future or the dimension is populated ahead of time?

This method may not be the most efficient but it is the most robust I have come across to date. If anyone has a better way drop me a comment. Always looking to improve/evolve.

Indexes are bad?

Indexes on your tables are not always a good thing. For example, a clustered index in the wrong place can dramatically slow down your update, insert and delete speeds. Indexes that are not being used sap valuable resources away from your database engine to maintain them. There are many instances where indexes will not enhance performance but for now I just want to deal with redundant ones.

I cannot take credit for this script and I cannot remember where I found it (please leave a comment if you know the original source and I will add the credit in). It finds all indexes (in the context of the database you are connected to) and orders them according to the total of index seeks, scans and lookups against them. Any of those with zero to very little should be dropped if resources are skant. It is the best one I have found to date. Again if you have found a better one please leave a comment.

Enjoy…


SELECT QUOTENAME(s.name) + '.' + QUOTENAME(t.name) AS TableName,
i.name AS IdxName,
i.type_desc AS IdxType,
ius.user_seeks,
(ius.user_seeks*1.) / NULLIF((ius.user_seeks+ius.user_scans+ius.user_lookups),0) AS [%Seek],
ius.user_scans,
(ius.user_scans*1.) / NULLIF((ius.user_seeks+ius.user_scans+ius.user_lookups),0) AS [%Scan],
ius.user_lookups,
(ius.user_lookups*1.) / NULLIF((ius.user_seeks+ius.user_scans+ius.user_lookups),0) AS [%Lookup],
ius.user_updates
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats ius
ON ius.object_id = i.object_id
AND ius.index_id = i.index_id
AND database_id = DB_ID()--Current DB
INNER JOIN sys.tables t
ON t.object_id = i.object_id
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
WHERE t.type = 'U'
AND t.is_ms_shipped = 0
ORDER BY ius.user_seeks + ius.user_scans + ius.user_lookups ASC

IsAggregatable = False

I was recently playing about with hiding the All member for several dimension attributes in my SSAS project. In order to hide the All member we set the IsAggregatable property to False. This immediately had the effect of my queries not returning any results. In hindsight my problem should have been blindingly obvious.

When we no longer aggregate the members on a dimension attribute, SSAS does not know what member/members to use unless you tell it explcitly, or set the DefaultMember attribute. Doing one or the other will stop your measures and calculations from vanishing.

SSIS file connections using dynamic variables and SQL Server Agent

The guy that thinks up my posting titles has caught a flesh eating virus. He could lose some weight though as he was always a bit porky.

Recently I encounted the most infuriating problem with SSIS, SQL Server Agent or Windows Server 2008 to date. What it is, I dont particuarly care I just pray this issue is fixed soon.

I have a set of user defined variables sitting in an SQL Server 2008 database. These are used to generate connection strings, rainbows, pixies and other mythical creatures through expressions in an SSIS project. This works a treat when running the package in the SSIS Package Execution Utility or Business Intelligence Studio (BIS). It saves me having to change variables in each package every time I deploy to different servers. If you try running a package with file connections populated by dynamic variables through SQL Server Agent, it cannot find the specified package (the precise error I will edit in later when I can be bothered to reproduce it again – it comes with the usual completely useless hexadecimal HRESULT nonsense so you won’t be disappointed). What is particuarly aggravating is that if you boot up the very handy Process Monitor you can see as clear as day the SSIS process (dtexec.exe) is a lying git. It only throws the error 50% of the time and yet the SSIS process finds the package quite happily 100%, every time.

I really did not want to define the file connection paths explicitly but I had no alternative. I got the same bull when I tried to run it through the Windows Scheduler to no avail. I tried everything. My futile attempts are way too numerous to list here. There is NO other way around this problem.

I cannot state whether or not this occurs in W2K3 as all our servers have been downgraded to W2K8. Enough cynicism from me for today. Here is something to warm you up: 27bslash6. Enjoy and till next time.

Return top