SQL Server (2014) Stored Procedure doesn't exist [duplicate] - sql-server

I have this query and I get the error in this function:
var accounts = from account in context.Accounts
from guranteer in account.Gurantors
select new AccountsReport
{
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
DateOpened = account.DateOpened,
};
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
})
.OrderBy(c=>c.FormattedRecordNumber)
.ThenByDescending(c => c.StateChangeDate);
public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
return (from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
select h.LastUpdated).Max();
}
Error is:
There is already an open DataReader associated with this Command which must be closed first.
Update:
stack trace added:
InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.]
System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) +5008639
System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) +23
System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) +144
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +87
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +443
[EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +479
System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +683
System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +119
System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +38
System.Linq.Enumerable.Single(IEnumerable`1 source) +114
System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3(IEnumerable`1 sequence) +4
System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable`1 query, Expression queryRoot) +29
System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) +91
System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(Expression expression) +69
System.Linq.Queryable.Max(IQueryable`1 source) +216
CreditRegistry.Repositories.CreditRegistryRepository.DateLastUpdated(Int64 creditorRegistryId, String accountNo) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1497
CreditRegistry.Repositories.CreditRegistryRepository.<AccountDetails>b__88(AccountsReport account, Int32 index) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1250
System.Linq.<SelectIterator>d__7`2.MoveNext() +198
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
System.Linq.<GetEnumerator>d__0.MoveNext() +96

This can happen if you execute a query while iterating over the results from another query. It is not clear from your example where this happens because the example is not complete.
One thing that can cause this is lazy loading triggered when iterating over the results of some query.
This can be easily solved by allowing MARS in your connection string. Add MultipleActiveResultSets=true to the provider part of your connection string (where Data Source, Initial Catalog, etc. are specified).

You can use the ToList() method before the return statement.
var accounts =
from account in context.Accounts
from guranteer in account.Gurantors
select new AccountsReport
{
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
DateOpened = account.DateOpened,
};
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
})
.OrderBy(c=>c.FormattedRecordNumber)
.ThenByDescending(c => c.StateChangeDate)
.ToList();
public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
var dateReported = (from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
select h.LastUpdated).Max();
return dateReported;
}

Use the syntax .ToList() to convert object read from db to list to avoid being re-read again.

Here is a working connection string for someone who needs reference.
<connectionStrings>
<add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>

In my case, using Include() solved this error and depending on the situation can be a lot more efficient then issuing multiple queries when it can all be queried at once with a join.
IEnumerable<User> users = db.Users.Include("Projects.Tasks.Messages");
foreach (User user in users)
{
Console.WriteLine(user.Name);
foreach (Project project in user.Projects)
{
Console.WriteLine("\t"+project.Name);
foreach (Task task in project.Tasks)
{
Console.WriteLine("\t\t" + task.Subject);
foreach (Message message in task.Messages)
{
Console.WriteLine("\t\t\t" + message.Text);
}
}
}
}

I dont know whether this is duplicate answer or not. If it is I am sorry. I just want to let the needy know how I solved my issue using ToList().
In my case I got same exception for below query.
int id = adjustmentContext.InformationRequestOrderLinks.Where(
item => item.OrderNumber == irOrderLinkVO.OrderNumber
&& item.InformationRequestId == irOrderLinkVO.InformationRequestId)
.Max(item => item.Id);
I solved like below
List<Entities.InformationRequestOrderLink> links =
adjustmentContext.InformationRequestOrderLinks
.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber
&& item.InformationRequestId == irOrderLinkVO.InformationRequestId)
.ToList();
int id = 0;
if (links.Any())
{
id = links.Max(x => x.Id);
}
if (id == 0)
{
//do something here
}

It appears that you're calling DateLastUpdated from within an active query using the same EF context and DateLastUpdate issues a command to the data store itself. Entity Framework only supports one active command per context at a time.
You can refactor your above two queries into one like this:
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = (
from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
select h.LastUpdated
).Max(),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
})
.OrderBy(c=>c.FormattedRecordNumber)
.ThenByDescending(c => c.StateChangeDate);
I also noticed you're calling functions like FormattedAccountNumber and FormattedRecordNumber in the queries. Unless these are stored procs or functions you've imported from your database into the entity data model and mapped correct, these will also throw excepts as EF will not know how to translate those functions in to statements it can send to the data store.
Also note, calling AsEnumerable doesn't force the query to execute. Until the query execution is deferred until enumerated. You can force enumeration with ToList or ToArray if you so desire.

In my case, I had opened a query from data context, like
Dim stores = DataContext.Stores _
.Where(Function(d) filter.Contains(d.code)) _
... and then subsequently queried the same...
Dim stores = DataContext.Stores _
.Where(Function(d) filter.Contains(d.code)).ToList
Adding the .ToList to the first resolved my issue. I think it makes sense to wrap this in a property like:
Public ReadOnly Property Stores As List(Of Store)
Get
If _stores Is Nothing Then
_stores = DataContext.Stores _
.Where(Function(d) Filters.Contains(d.code)).ToList
End If
Return _stores
End Get
End Property
Where _stores is a private variable, and Filters is also a readonly property that reads from AppSettings.

As a side-note...this can also happen when there is a problem with (internal) data-mapping from SQL Objects.
For instance...
I created a SQL Scalar Function that accidentally returned a VARCHAR...and then...used it to generate a column in a VIEW. The VIEW was correctly mapped in the DbContext...so Linq was calling it just fine. However, the Entity expected DateTime? and the VIEW was returning String.
Which ODDLY throws...
"There is already an open DataReader associated with this Command
which must be closed first"
It was hard to figure out...but after I corrected the return parameters...all was well

In addition to Ladislav Mrnka's answer:
If you are publishing and overriding container on Settings tab, you can set MultipleActiveResultSet to True. You can find this option by clicking Advanced... and it's going to be under Advanced group.

I solved this problem by changing
await _accountSessionDataModel.SaveChangesAsync();
to
_accountSessionDataModel.SaveChanges();
in my Repository class.
public async Task<Session> CreateSession()
{
var session = new Session();
_accountSessionDataModel.Sessions.Add(session);
await _accountSessionDataModel.SaveChangesAsync();
}
Changed it to:
public Session CreateSession()
{
var session = new Session();
_accountSessionDataModel.Sessions.Add(session);
_accountSessionDataModel.SaveChanges();
}
The problem was that I updated the Sessions in the frontend after creating a session (in code), but because SaveChangesAsync happens asynchronously, fetching the sessions caused this error because apparently the SaveChangesAsync operation was not yet ready.

For those finding this via Google;
I was getting this error because, as suggested by the error, I failed to close a SqlDataReader prior to creating another on the same SqlCommand, mistakenly assuming that it would be garbage collected when leaving the method it was created in.
I solved the issue by calling sqlDataReader.Close(); before creating the second reader.

Most likely this issue happens because of "lazy loading" feature of Entity Framework. Usually, unless explicitly required during initial fetch, all joined data (anything that stored in other database tables) is fetched only when required. In many cases that is a good thing, since it prevents from fetching unnecessary data and thus improve query performance (no joins) and saves bandwidth.
In the situation described in the question, initial fetch is performed, and during "select" phase missing lazy loading data is requested, additional queries are issued and then EF is complaining about "open DataReader".
Workaround proposed in the accepted answer will allow execution of these queries, and indeed the whole request will succeed.
However, if you will examine requests sent to the database, you will notice multiple requests - additional request for each missing (lazy loaded) data. This might be a performance killer.
A better approach is to tell to EF to preload all needed lazy loaded data during the initial query. This can be done using "Include" statement:
using System.Data.Entity;
query = query.Include(a => a.LazyLoadedProperty);
This way, all needed joins will be performed and all needed data will be returned as a single query. The issue described in the question will be solved.

The same error happened to me when I was looping and updating data on
IEnumerable<MyClass>
When I changed the looped-on collection to be List<MyClass>, and filled it by converting by .ToList(), it solved and updated without any errors.

I had the same error, when I tried to update some records within read loop.
I've tried the most voted answer MultipleActiveResultSets=true and found, that it's just workaround to get the next error 
New transaction is not allowed because there are other threads running
in the session
The best approach, that will work for huge ResultSets is to use chunks and open separate context for each chunk as described in 
SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session

Well for me it was my own bug. I was trying to run an INSERT using SqlCommand.executeReader() when I should have been using SqlCommand.ExecuteNonQuery(). It was opened and never closed, causing the error. Watch out for this oversight.

This is extracted from a real world scenario:
Code works well in a Stage environment with MultipleActiveResultSets is set in the connection string
Code published to Production environment without MultipleActiveResultSets=true
So many pages/calls work while a single one is failing
Looking closer at the call, there is an unnecessary call made to the db and needs to be removed
Set MultipleActiveResultSets=true in Production and publish cleaned up code, everything works well and, efficiently
In conclusion, without forgetting about MultipleActiveResultSets, the code might have run for a long time before discovering a redundant db call that could be very costly, and I suggest not to fully depend on setting the MultipleActiveResultSets attribute but also find out why the code needs it where it failed.

I am using web service in my tool, where those service fetch the stored procedure. while more number of client tool fetches the web service, this problem arises. I have fixed by specifying the Synchronized attribute for those function fetches the stored procedure. now it is working fine, the error never showed up in my tool.
[MethodImpl(MethodImplOptions.Synchronized)]
public static List<t> MyDBFunction(string parameter1)
{
}
This attribute allows to process one request at a time. so this solves the Issue.

In my case, I had to set the MultipleActiveResultSets to True in the connection string.
Then it appeared another error (the real one) about not being able to run 2 (SQL) commands at the same time over the same data context! (EF Core, Code first)
So the solution for me was to look for any other asynchronous command execution and turn them to synchronous, as I had just one DbContext for both commands.
I hope it helps you

Related

EF Core 3.1.9 - FromRawSql using stored procedures stopped working - 'The underlying reader doesn't have as many fields as expected.'

At one point using FromSqlRaw to call stored procedures worked for me. I did not change anything in the project but now calling any stored procedure using FromSqlRaw returns
The underlying reader doesn't have as many fields as expected
I removed the model from the project and performed a BUILD. Then added the model back with no luck. I reduced the model and stored procedure to return a single column, no luck.
I tried adding Microsoft.EntityFrameworkCore.Relational as a dependency, no luck. All my unit test that use FromSqlRaw to call a stored procedure return the same error and at one time they all worked.
I have received Windows updates but nothing I know about that would have affected EF Core. I have run through all internet problem solving I can find. I am starting to think I will need to use ADO as a work around but I do not want a work around when it worked for me at one point. Something changed on my machine but I am not sure what to cause this problem.
Here is my test method in case my code is messed up. It is very straight forward not much to mess up. I tried the "var" out of desperation.
[TestMethod]
public void WorkOrderBOMGridABS()
{
List<WorkOrderBOMGridABS> baseList = new List<WorkOrderBOMGridABS>();
using (WorkOrderDataContext context = new WorkOrderDataContext())
{
var param = new SqlParameter[] {
new SqlParameter() {
ParameterName = "#WorkOrderId",
SqlDbType = System.Data.SqlDbType.Int,
Direction = System.Data.ParameterDirection.Input,
Value = 38385
}
};
baseList = context.WorkOrderBOMGridABS.FromSqlRaw("[dbo].[WorkOrderBOMGridABS] #WorkOrderId", param).ToList();
//var results = context.WorkOrderBOMGridABS.FromSqlRaw("[dbo].[WorkOrderBOMGridABS] #WorkOrderId", param).ToList();
Assert.IsNotNull(baseList);
}
}
I was using an old table to get the Unit Of Measure value that had an integer ID value. I switched it to use a new table with a VARCHAR ID value. Making this change to the stored proc and model code allowed the FromRawSql to work. Not sure why because while the integer ID value was getting an integer, either 0 or number other than 0, it was a valid value for the model. Any error message I received did not mention this UnitId field. It was a pain but I am glad it is resolved. At least until the next error I run into that much is guaranteed.

SQL Server 2012 assembly execution failure - System.NullReferenceException: Object reference not set to an instance of an object

I am trying to execute a UDF which uses a CLR assembly. Each time I try to run it I get the below error:
Msg 6522, Level 16, State 1, Line 45
A .NET Framework error occurred during execution of user-defined routine or aggregate "Geocode":
System.NullReferenceException: Object reference not set to an instance of an object.
at ProSpatial.UserDefinedFunctions.GeocodeUDF(SqlString countryRegion, SqlString adminDistrict, SqlString locality, SqlString postalCode, SqlString addressLine)
It is a geocoding assembly, which is based on the below blog:
https://alastaira.wordpress.com/2012/05/04/geocoding-in-sql-server-with-the-bing-maps-locations-api/
Is there anything I can do to fix it? It was working fine, but just stopped working recently. I changed the Bing Maps key to a new one, but that hasn't resolved the issue. Anyone have any ideas?
Cheers
Edit: I entered a formatted URL into Chrome, to see if I can get the error. I entered the below URL format:
http://dev.virtualearth.net/REST/v1/Locations?countryRegion={0}&adminDistrict={1}&locality={2}&postalCode={3}&addressLine={4}&key={5}&output=xml
All I did was to replace items 0 to 5 with their respective entries. I left the curly brackets in there, and then also tried it without the curly brackets. Without the curly brackets, the URL returned a result with no issues.
In the browser, I am getting geocoded results, but not in SQL any more
Just worked it out. One of the address fields that was being geocoded was null in the database, and the API did not like that. So I removed that from the geocoding list
Looking at the code in that blog, if you are passing in a NULL, then it's not the API that's throwing the error. The error is happening because NULL values are not being handled when the method is first called. The code just casts the SqlString input parameters to string without first checking to see if there is a value in the SqlString variable. SqlString is very similar to a nullable string.
Fortunately, it is rather easy to adjust the code to properly handle NULL values in the input parameters. Starting with a redacted snippet of the original code below, I will show how to do this for one parameter and you can repeat that modification for the others (well, the ones that might actually be NULL in the DB; no need to do this for parameters that are guaranteed to be there due to being in a NOT NULL column).
public static SqlGeography GeocodeUDF(
SqlString countryRegion,
SqlString adminDistrict,
SqlString locality,
SqlString postalCode,
SqlString addressLine
)
{
...
string localAdminDistrict = string.Empty;
if (!adminDistrict.IsNull)
{
localAdminDistrict = adminDistrict.Value;
}
// Attempt to geocode the requested address
try
{
geocodeResponse = Geocode(
(string)countryRegion,
localAdminDistrict,
(string)locality,
(string)postalCode,
(string)addressLine
);
}
All I did was:
Added a local variable for localAdminDistrict, defaulted to an empty string.
Added an if block to set localAdminDistrict if adminDistrict is not null.
Updated the call to Geocode() to use localAdminDistrict instead of (string)adminDistrict.
This should work as long as the Bing Maps API is ok with an empty value for adminDistrict (i.e. ...&adminDistrict=&locality=... ), as opposed to adminDistrict not being present in the GET request (which is easy enough, it just requires an additional modification).
ALSO: As long as you are going to be in there updating the code, you really should move the calls to the Close() and Dispose() methods into a finally block for that try / catch.
For more info on working with SQLCLR in general, please visit: SQLCLR Info

Migrating working ServiceStack to live causes Unable to cast object of type 'System.Byte' to type 'System.String'

I have developed a ServiceStack API, using ORMLite based on a SQL Server. The app works perfectly pointing at both my local SQL database and an Azure database. Happy Days!
I have now tried to move this solution to the live server which has it's own local copy of the same database and I am getting strange results. The error is:
Error Code: InvalidCastException
Message: Unable to cast object of type 'System.Byte' to type 'System.String'.
[EMEM: 1/16/2014 11:49:29 AM]: [REQUEST: {Equipment:DP112}]
System.InvalidCastException: Unable to cast object of type 'System.Byte' to type 'System.String'. at lambda_method(Closure , Object , Object ) at
ServiceStack.OrmLite.OrmLiteDialectProviderBase`1.SetDbValue(FieldDefinition fieldDef, IDataReader dataReader, Int32 colIndex, Object instance) at
ServiceStack.OrmLite.ReadExtensions.ExprConvertToList[T](IDataReader dataReader) at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ExprConvertToList[T](IDbCommand dbCmd, String sql) at
ServiceStack.OrmLite.ReadConnectionExtensions.Exec[T](IDbConnection dbConn, Func`2 filter) at
ViewPoint.EquipmentService.Get(EMEM request) at
ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)
I have checked the database schemas and they look identical.
This is the code that works on 2 out of the 3 databases quite happily but not the third.
public object Get(EMEM request)
{
var dbFactory = new OrmLiteConnectionFactory(WebConfigurationManager.ConnectionStrings["db"].ToString(), SqlServerDialect.Provider);
using (IDbConnection db = dbFactory.OpenDbConnection())
{
if (request.Equipment == null)
{
List<EMEM> results = db.Select<EMEM>();
return results;
}
else
{
List<EMEM> results = db.Select<EMEM>(p => p.Where(ev => ev.Equipment == request.Equipment));
return results;
}
}
}
I can literally fix the problem by pointing the connection string at the azure database which tends to suggest it's database related(?)
Extra Information:
I have also written a put method which updates a row in the database and that works fine.
On 2 of the servers EMEM is a table but on the third, where it doesn't work, it's a View.
Can anyone suggest where to start looking for this problem?
UPDATE: I have now created a View on my local development database so it should now be identical to the live database. I was expecting this to break the local dev site but it hasn't... :(
BINGO! FIXED IT!
IT WAS linked to the View, but it wasn't the View's fault....
The view was looking at a table with different data types against most of the values. The demo table I was working against had all the columns set to String!
So, look out when people give you "demo tables, with identical data to the live" to develop against.
They aren't always identical!!
HTH

Using CONTAINS from HQL / Criteria API

I'm using NHibernate 2.1.2.4000GA. I'm trying to use SQL Server's CONTAINS function from within HQL and the criteria APIs. This works fine in HQL:
CONTAINS(:value)
However, I need to qualify the table in question. This works fine:
CONTAINS(table.Column, :value)
However, I need to search across all indexed columns in my table. I tried this:
CONTAINS(table.*, :value)
But I get:
NHibernate.Hql.Ast.ANTLR.QuerySyntaxException : Exception of type 'Antlr.Runtime.MissingTokenException' was thrown. near line ... [select table.Id from Entities.Table table where CONTAINS(table.*,:p0) order by table.Id asc]
at NHibernate.Hql.Ast.ANTLR.ErrorCounter.ThrowQueryException()
at NHibernate.Hql.Ast.ANTLR.HqlParseEngine.Parse()
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Parse(Boolean isFilter)
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow)
at NHibernate.Engine.Query.HQLQueryPlan..ctor(String hql, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(String queryString, Boolean shallow, IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(String query, Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(String queryString)
So it would seem the HQL parser chokes on the asterisk. I thought of doing this:
CONTAINS(table.Column1, :value) or CONTAINS(table.Column2, :value)
Not only is this inefficient, it can also yields incorrect results depending on the full text predicate in :value.
I tried customizing my dialect as per these instructions, but that doesn't help because you're still left with the same problem: specifying table.* causes the HQL parser to fall over.
I thought of specifying query substitutions:
<property name="query.substitutions">TABLECONTAINS(=CONTAINS(table.*,</property>
And then simply doing:
TABLECONTAINS(:value)
But that does not work. I'm not sure why - judging by the resultant error, the substitution just doesn't take place because "TABLECONTAINS" is still present in the query. Besides, this wouldn't work for all cases because I'd need to know the alias of the table and dynamically substitute it in.
Therefore, I rolled an interception-based approach:
using System;
using NHibernate;
using NHibernate.SqlCommand;
public class ContainsInterceptor : EmptyInterceptor
{
public override SqlString OnPrepareStatement(SqlString sql)
{
var indexOfTableContains = sql.IndexOfCaseInsensitive("TABLECONTAINS(");
if (indexOfTableContains != -1)
{
var sqlPart = sql.ToString();
var aliasIndex = sqlPart.LastIndexOf("Table ", indexOfTableContains, StringComparison.Ordinal);
if (aliasIndex == -1)
{
return sql;
}
aliasIndex += "Table ".Length;
var alias = sqlPart.Substring(aliasIndex, sqlPart.IndexOf(" ", aliasIndex, StringComparison.Ordinal) - aliasIndex);
sql = sql.Replace("TABLECONTAINS(", "CONTAINS(" + alias + ".*,");
}
return base.OnPrepareStatement(sql);
}
}
This works and I will now be able to sleep tonight, but I do feel a sudden desire to attend London's impending papal procession and shout out a confession.
Can anyone suggest a better way to achieve this?
Why not use an ISQLQuery instead?
You can still retrieve entities, see http://nhibernate.info/doc/nh/en/index.html#querysql-creating
I would think that a custom dialect would be the appropriate way to handle this. You can find some guidance in this article. I've used this approach to register SQL Server-specific functions like ISNULL for use in our projects.

Cannot retrieve user object from foreign key relationships using Linq to Entities statement

I'm trying to retrieve a user object from a foreign key reference but each time I try to do so nothing gets returned...
My table is set up like this:
FBUserID long,
UserID uniqueidentifier
so I have my repository try to get the User when it's provided the FBUserID:
public User getUserByFBuid(long uid)
{
User fbUser = null;
IEnumerable<FBuid> fbUids = _myEntitiesDB.FBuidSet.Where(user => user.FBUserID == uid);
fbUser = fbUids.FirstOrDefault().aspnet_Users;
return fbUser;
}
I've checked that the uid (FBUserID) passed in is correct, I've check that the UserID is matched up to the FBUserID. And I've also checked to make sure that fbUids.Count() > 0...
I've returned fbUids.FirstOrDefault().FBUserID and gotten the correct FBUserID, but any time I try to return the aspnet_Users or aspnet_Users.UserName, etc... I don't get anything returned. (I'm guessing it's getting an error for some reason)
I don't have debugging set up properly so that's probably why i'm having so much troubles... but so far all the checking I've done I've been doing return this.Json(/* stuff returned form the repository */) so that I can do an alert when it gets back to the javascript.
Anyone know why I would have troubles retrieving the user object from a foreign key relationship like that?
Or do you have any suggestions as to finding out what's wrong?
For now, with Entity Framework 1, you don't get automatic delayed loading, e.g. if you want to traverse from one entity to the next, you need to either do an .Include("OtherEntity") on your select to include those entities in the query, or you need to explicitly call .Load("OtherEntity") on your EntityContext to load that entity.
This was a design decision by the EF team not to support automagic deferred loading, since they considered it to be too dangerous; they wanted to make it clear and obvious to the user that he is also including / loading a second set of entities.
Due to high popular demand, the upcoming EF v4 (to be released with .NET 4.0 sometime towards the end of 2009) will support the automatic delayed loading - if you wish to use it. You need to explicitly enable it since it's off by default:
context.ContextOptions.DeferredLoadingEnabled = true;
See some articles on that new feature:
A Look at Lazy Loading in EF4
POCO Lazy Loading
Don't know if this is what you are asking but i do a join like so;
var votes = from av in dc.ArticleVotes
join v in dc.Votes on av.voteId equals v.id
where av.articleId == articleId
select v;
Did this help or am I off base?

Resources