Every repository with this icon (
Every repository with this icon (
| Description: | SubSonic 3.0 for the .NET 3.5 Framework edit |
-
IsNextPage in the pagedList class is getting calcualted wrong... It should be
public bool IsNextPage { get { return ((PageIndex + 1) * PageSize) <= TotalCount; } }Comments
-
Steps to reproduce:
- Using SimpleRository and SQL server as you backend, create a C# class and run a Subsonic migration. This will create the corresponding table on the SQL server
- Add a non-nullable DateTime field to the C# class and run migration again
Expected behavior
You expect a new DataTime field to be added to the SQL table and also all the existing records to be updated with the value '1/1/1900' in the new field.
Observed behavior
The new field is not created, the and the following error is thrown:
Message: Incorrect syntax near '1'. Source: System.Exception {System.Data.SqlClient.SqlException Stack trace: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at SubSonic.Query.BatchQuery.ExecuteTransaction() in F:\Users\Jericho\Documents\Visual Studio 2008\Projects\SubSonic 3 Source\SubSonic.Core\Query\BatchQuery.cs:line 198
Cause of the problem
On line 165 in Sql2005Schema.cs, single quotes are added to the default value
*line 165:* column.DefaultSetting = string.Format("'{0}'", column.DefaultSetting);and also on line 86 in ANSISchemaGenerator.cs single quotes are again added to the default value
*line 86:* sql.AppendFormat("UPDATE {0} SET {1}='{2}';", tableName, column.Name, column.DefaultSetting);The result is the following query (notice the double single quotes surrounding the default date value):
UPDATE MyTests SET NewDateField=''1/1/1900 12:00:00 AM''Solution
Change the following block of code (lines 162-169 in Sql2005Schema.cs):
var defaultType = column.DefaultSetting.GetType(); if (defaultType == typeof(string) || defaultType == typeof(DateTime)) { if(!column.DefaultSetting.ToString().EndsWith("()")) column.DefaultSetting = string.Format("'{0}'", column.DefaultSetting); } sb.Append(" CONSTRAINT DF_" + column.Table.Name + "_" + column.Name + " DEFAULT (" + column.DefaultSetting + ")");With the following:
var defaultType = column.DefaultSetting.GetType(); var defaultValue = column.DefaultSetting; if (defaultType == typeof(string) || defaultType == typeof(DateTime)) { if(!column.DefaultSetting.ToString().EndsWith("()")) defaultValue = string.Format("'{0}'", defaultValue); } sb.Append(" CONSTRAINT DF_" + column.Table.Name + "_" + column.Name + " DEFAULT (" + defaultValue + ")");Comments
- Using SimpleRository and SQL server as you backend, create a C# class and run a Subsonic migration. This will create the corresponding table on the SQL server
-
Bugfix [ready to pull]: Tinyint(1) columns broken in MySQL
4 comments Created 4 months ago by defacerAnyone who wants to store boolean values in MySQL has to do one of the following:
- Use "bit". This doesn't work because MySQL extends this type up to 64 bits, so Connector/.NET implements such columns as (U?)Int64 while SubSonic makes them Boolean. Bam, exception on conversion.
- Use "bool". This doesn't work because MySQL treats "bool" as "tinyint(1)".
- Use "tinyint(1)". This doesn't work currently because Connector/.NET returns data from tinyint(1) as boolean values (at the same time it returns tinyint(N) with N > 1 as SByte!) while SubSonic makes them SByte. Exception on conversion.
The last case can be fixed entirely in SubSonic, and is the subject of this issue. Two things must be done:
- Make the SS3 templates implement tinyint(1) columns as boolean properties. The patch to do this is here: http://github.com/defacer/SubSonic-3.0-Templates/commit/bbcd4bd197e1ee60182763527e1ac90a7f714f3b, it exposes a "TreatTinyint1AsBoolean" setting which defaults to false (consistent with previous behavior).
- Make SubSonic.Core correctly recognize the values returned by Connector/.NET for tinyint(1) fields (bool) and convert them to the backing property type (bool). This is currently broken because of special handling code for bool properties in SubSonic.Core\Extensions\Database.cs. The patch to special-case (not being aware of why it was put there, I didn't remove it entirely) the special-case is here: http://github.com/defacer/SubSonic-3.0/commit/e31a5f75101a1e23fccb40a2c66ad55d016722c4
PLEASE pull this into the repository. :-)
Comments
After reading more comments from people who have the exact problem (in SQL Server even):
Looks like this is a regression caused by this commit: http://github.com/subsonic/SubSonic-3.0/commit/66775287d34814b9ea56b97769668c45329e553e
Why did that "if" get in there in the first place? First of all, if none of the two clauses are true, the conversion is handed off to SubSonic.Extensions.Objects.ChangeTypeTo() which checks its own special cases before typically handing off to Convert.ChangeType(). Why have special case checks in two places and not put this into ChangeTypeTo?
For that matter, why have this special case at all? If it were allowed to reach Convert.ChangeType() it would work just fine in all cases (ChangeType says that conversions of integers, booleans and strings to boolean are guaranteed to be performed without exceptions).
The more I look at this "if" the more I can't understand what its purpose is.
johnsheehan
Sat Aug 08 00:07:16 -0700 2009
| link
I thought I responded to this, but I don't see it. Nice work tracking this down. I think as a start that regression needs to be reversed until that SByte to Boolean change can be justified (I can't find an issue for it). I'm assuming its for some non MSSQL/MySql database provider.
The funny thing is that I read that if (as it stood before the regression) as "if the backing property is of SByte type, set its value to boolean true/false depending on whether blah blah is equal to the string "1"".
Wouldn't that Sbyte = boolean always throw?
- Use "bit". This doesn't work because MySQL extends this type up to 64 bits, so Connector/.NET implements such columns as (U?)Int64 while SubSonic makes them Boolean. Bam, exception on conversion.
-
Like-statement in query fails for DbTypes other than strings
2 comments Created 4 months ago by mattsbI noticed that my queries failed, when using the LIKE-command om columns specified as int or double. This is because constraint is created as the same Datatype as the column, but when inserting wild cards into the constraint, these are no longer ints nor doubles.
A typical fail would be "Failed to convert parameter value from a String to a Int32.". A quick search on "the Net" revealed to me that I was not the first person to encounter this.
I fixed this by inserting this code into SubSonic.Code/Query/SqlQuery.cs, in the method SetConstraintParams(SqlQuery qry, QueryCommand cmd), before the last else-statement:
else if (c.Comparison == Comparison.Like)
{cmd.Parameters.Add(c.ParameterName, c.ParameterValue, DbType.AnsiString);}
This way, the paramater datatype in LIKE-statements are treated as strings, thus allowing wild cards to be send.
Comments
Also, I have seen that this occurs in version 2.* as well..
-
i saw double
symbol instead if single while generating sql for MySql. my workaround is to add .Replace("","") everewhere.Comments
I think, that samshich had to say, that when sql query generated for MySQL, it's contain dobule apostrophe symbol... Example of query and what query tool is used? Linq or old query tool?
exactly mr Stetler:)
old query tool with groupby and inner join
-
file ANSISqlGenerator.cs
function GenerateGroupBy() always returns empty string
patch is
public override string GenerateGroupBy() { string result = String.Empty; if(query.Aggregates.Count > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); bool isFirst = true; foreach(Aggregate agg in query.Aggregates) { if(agg.AggregateType == AggregateFunction.GroupBy) { if(!isFirst) sb.Append(", "); else sb.Append(SqlFragment.GROUP_BY); sb.Append(string.Format("`{0}`", agg.ColumnName)); isFirst = false; } } result = sb.ToString(); } return result; }same thing in MySqlGenerator.cs
public override string GenerateGroupBy() { string result = String.Empty; if(query.Aggregates.Count > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); bool isFirst = true; foreach(Aggregate agg in query.Aggregates) { if(agg.AggregateType == AggregateFunction.GroupBy) { if(!isFirst) sb.Append(", "); else sb.Append(SqlFragment.GROUP_BY); sb.Append(string.Format("`{0}`", agg.ColumnName)); isFirst = false; } } result = sb.ToString(); }Comments
-
NULL constraints generating incorrect SQL using lambdas
1 comment Created 4 months ago by jesseemerickA quick run through the source leads me to believe this would happen for anything -- so far I've just been using SimpleRepository. Redoing things in IQueryable format seems to work just fine. Here's the screenshot: http://screencast.com/users/jemerick/folders/Jing/media/e628a082-83b5-4cd5-a253-140dff8b7e93
Essentially "!= null" in the lambda expression is being translated as "<> null" when it needs to be "IS NOT NULL". The commented section below with the IQueryable works just fine...
Comments
-
newid() default value for uniqueidentifier ignored in MS SQL Server
2 comments Created 4 months ago by samsalisburyIf you have a table in SQL Server that has as its primary key a uniqueidentifier field, with the default value set to (newid()), and then create a new instance of the class relating to that table, and save it, it always attempts to save the ID as Guid.Empty, unless you manually specify the ID in the code.
Is there a way to have the newid() default value respected by subsonic? If someone points me in the right direction I might be able to contribute a fix for this...
As temporary workaround, I've implemented the OnCreated() function for the generated class, to test if the ID == Guid.Empty, and if so to generate a new ID (Guid.New()) for the instance.
(Edit: here's my workaround method just to be clear...)
partial void OnCreated() { if (this.Id == Guid.Empty) { this.Id = Guid.NewGuid(); } }Comments
I actually thought I saw this fixed...however, I see that it has not been. Time to dive into the templates I think the fix can go there, however my guess is it should be in the core library.
-
Hello I'm getting this error when I try to have two Primary Key "Multiple identity columns specified for table 'TblUsersGroups'. Only one identity column per table is allowed."
I need to have two Primary Key in this table.
Is there a fix for this please help.....
public class TblUsersGroup { [SubSonicPrimaryKey] public int UserID { get; set; } [SubSonicPrimaryKey] public int GroupID { get; set; } }Comments
Which method that are you using? ActiveRecords or SimpleRepository?
-
Could you please add a method to SubsonicRepository that does a GetPaged with an expression.
I have tried _repository.GetPaged(sortBy, pageNumber, 20).Where(x => x.IsAdmin == false) but this returns 20 items then removes 10. I want to return 20 items that are false.
Comments
-
ActiveRecord.Destroy(expression) does not call right method
3 comments Created 4 months ago by jcoenenEDIT: See the comments below - this is actually due to the TestRepository not being entirely fleshed out.
From what I can tell I think the Destroy method is calling the wrong method on the repo and thus not working. Basically what I'm trying to do is delete all the records in the table for cleanup after my unit tests - so I wrote something like
Product.Destroy(p=>p.ProductId > -1);
but it never deleted anything. I stepped through and got to this generated code which I think should be calling DeleteMany(expression) instead because when you step through to IActiveRecord it is trying to go to Delete(object key)
public static void Destroy(Func<Product, bool> expression) {
var repo = GetRepo(); repo.Delete(expression); //I think this is wrong. }I did just trying changing the template to call repo.DeleteMany(expression), but then got a "cannot convert from 'System.Func<Thrive.Framework.Department,bool>' to 'System.Linq.Expressions.Expression<System.Func<Thrive.Framework.Department,bool>>'" error.
Is CodingHorror included in SS3? :-)
Comments
I'm actually having trouble destroying anything with the Test repo. Looping through and destroying each item in the collection doesn't work either.
Starting to think this is more TestRepository related than anything.
For example DeleteMany from TestRepository.cs
public int DeleteMany(Expression<Func<T, bool>> expression) { return 0; }and Find
public IQueryable<T> Find(Expression<Func<T, bool>> expression) { return _items.AsQueryable(); << returns all records! } -
Loading a Deleted object does not set IsDeleted to true
2 comments Created 4 months ago by jcoenenI'm using Subsonic 3.0.0.3 ActiveRecord templates.
Basically if you Delete a record it will go ahead and delete that record correctly by setting IsDeleted to true. But then if you load that item back up via SingleOrDefault IsDeleted remains false for some reason. Also another quirk is when you do the delete while it does correctly do the delete it adds another all null record to the Product.All() collection for some reason. I'm currently using the Test repo for all of my testing. Below is a sudo unit test - I could not create one for Northwind because there are no IsDeleted columns
public void Is_Deleted_Should_Be_True_For_DeletedItem()
{ Product.Setup(10); Assert.AreEqual(10, Product.All().Count()); //passes Product.Delete(p => p.ProductId==3,0); var product= Product.SingleOrDefault(p => p.ProductId == 3); Assert.IsTrue(product.IsDeleted); //fails - IsDeleted is false even though in the db it is true Assert.AreEqual(9, ConfigurationSetting.All().Count()); //fails is actually now 11 as a new null record gets added. It looks like All() returns deleted records too which is fine, but just thought I'd point out the extra record that gets created as well. }Comments
johnsheehan
Thu Aug 20 22:02:26 -0700 2009
| link
There's an issue right now (issue 95 covers it best) where ALL boolean fields are being set to false for items when they are retrieved.
-
Boolean columns always being set to false
13 comments Created 4 months ago by johnsheehanI'm using the Linq Templates. I've got a simple query:
var query = from u in DB.Users where u.ExternalKey == key select u;Any bool props on the users returned that are always set to false, even if database value is true. I'm running the latest rev.
Comments
I 'm seeing the same behavior John, using MySQL with the bool props stored as tinyint(1) in the database. Is this your case too?
In my case, I 've found the cause of the problem (MySQL Connector/NET is at fault) and it can be solved by adding a tiny workaround in SubSonic.Core.dll.
I'm using SQL2005 when i add the a record using repo, the bool value is saved as datatype bit in databese, when i retrieve it, its always false.
I can't debug this as I 'm not using MSSQL, but I 'm pretty sure that in your case too the problem is with this code here:
http://github.com/defacer/SubSonic-3.0/commit/e31a5f75101a1e23fccb40a2c66ad55d016722c4
Step through it in the debugger and most likely you 'll figure it out easily. Specifically, check out what rdr.GetValue(i) returns exactly, and what its ToString() representation is.
i've tested it in SQL2008 and works fine. Will step through the debugger tomorrow when i deal with a SQL2005 db again.
This is want I run
var tblUsers = from z in simpleRepository.All<TblUser>() where z.UserName == HttpContext.Current.Request.LogonUserIdentity.Name select z;I apologize wrong code:
var wmDb = new SubSonic.Repository.SimpleRepository(SimpleRepositoryOptions.None); var objLastLoginDate = wmDb.All<TblUser>().Single(z => z.ID == intUserId); objLastLoginDate.LastLoginDate = DateTime.Now; wmDb.Update(objLastLoginDate);
johnsheehan
Sat Aug 08 00:05:37 -0700 2009
| link
Resolution for this is covered in issue 95. There was a regression in this commit: http://github.com/subsonic/SubSonic-3.0/commit/66775287d34814b9ea56b97769668c45329e553e
I am observing the same problem with SQL 2008 and I don't think issue 95 covers it. The issue is that rdr.GetValue(i).ToString() return the string "True" as opposed to "1". Therefore to solve this problem we have to change line 166 in Database.cs with the following:
currentProp.SetValue(item, (rdr.GetValue(i).ToString() == "1" || rdr.GetValue(i).ToString().ToLowerInvariant() == "true"), null);and also change line 176:
currentField.SetValue(item, (rdr.GetValue(i).ToString() == "1" || rdr.GetValue(i).ToString().ToLowerInvariant() == "true"));
johnsheehan
Sat Aug 08 22:22:33 -0700 2009
| link
Issue 95 covers this because it exposes the regression that caused this bug. Adding another condition is patching the regression instead of reversing it, which is what I think needs to be done. Lines 165 and 175 should go back to checking for SByte and leave bools to be handled by the else branch.
Now I understand what you were saying! Indeed, changing lines 165 and 175 solve the problem.
By the way, I reported another issue (and offered a fix) related to boolean properties. Do you think it's related to this problem?
johnsheehan
Sun Aug 09 22:24:21 -0700 2009
| link
I haven't used SimpleRepository, but from what I can tell in that issue, it's not related to this.
-
I have this query:
var query = from u in DB.Users where u.ExternalKey == key select u;The bool columns (IsModerator, IsAdmin) are always false, even if they're true in DB. Using SQL 2005. Running latest rev.
Comments
johnsheehan
Wed Jul 29 20:59:34 -0700 2009
| link
Dupe sorry
-
Serialization Issue with SubSonic.Schema.DatabaseColumn
2 comments Created 5 months ago by miguelfelicianoAs found on StackOverflow: http://stackoverflow.com/questions/1193857/subsonic-3-0-0-2-structs-tt
The error I'm getting seems to be coming out of the Structs.tt file. I'm using the Northwind db and only using the Products table (I excluded all other tables). I return Json(Product.All()).
Here's the error:
A circular reference was detected while serializing an object of type 'SubSonic.Schema.DatabaseColumn'.Here's the Stack Trace:
System.InvalidOperationException was unhandled by user code Message="A circular reference was detected while serializing an object of type 'SubSonic.Schema.DatabaseColumn'." Source="System.Web.Extensions" StackTrace: at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat) at System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj) at System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.<>cDisplayClass11.be() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>cDisplayClass11.<>cDisplayClass13.b_10() at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) at System.Web.Mvc.Controller.ExecuteCore() at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) at System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest(IHttpHandler httpHandler, HttpContextBase httpContext) at System.Web.Routing.UrlRoutingHandler.ProcessRequest(HttpContextBase httpContext) at System.Web.Routing.UrlRoutingHandler.ProcessRequest(HttpContext httpContext) at System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext context) at ExtJSNorthwind.Default.Page_Load(Object sender, EventArgs e) in C:\Applications\Spikes\ExtJSNorthwind\ExtJSNorthwind\Default.aspx.cs:line 18 at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) InnerException:
Don't know if this will help to solve the problem, but as I dug deeper into the exception I ran into this: Message: "Method may only be called on a Type for which Type.IsGenericParameter is true." FullName: System.Web.Script.Serialization.JavaScriptSerializer
Comments
Hey has this been resolved?? I am running into the same problem.
You can get around this by serializing classes more friendly "to the wire". The problem, specifically, is that DatabaseColumn has a property named Table, and Table has a set of properties called "Column". These weren't meant to be serialized.
Your choice at this point is to remove the Columns bit from your template, or create a separate class for JSON work.
-
Rob asked me to log this after my question on Stack overflow: http://stackoverflow.com/questions/1182276/subsonic-batchquery-queue-causing-cant-decide-which-property-to-consider-the-ke
When using ActiveRecord, it appears the ToSchemaTable() method in Objects.cs is building out a table schema without referring to the generated table class, and an exception is thrown if said table has a PK other than ID. This makes since for SimpleRepository, but should not apply to ActiveRecord. I don't know all the methods that call this, but I encountered this error when using BatchQuery.Queue().
Full copy of the Stackoverflow QA is below:
I'm just getting started with Subsonic 3.0 ActiveRecord and am trying to implement a batch query like the one in the SubSonic docs. I'm using a batch so I can query a User and a list of the users Orders in one shot.
When I call the BatchQuery.Queue() method, adding my "select user" query, SubSonic throws the following exception:
System.InvalidOperationException : Can't decide which property to consider the Key - you can create one called 'ID' or mark one with SubSonicPrimaryKey attribute
The code is as follows:
var db = new MyDB();
var userQuery = from u in db.Users //gets user by uid
where u.uid == 1 select u;var provider = ProviderFactory.GetProvider();
var batch = new BatchQuery(provider);
batch.Queue(userQuery); //exception here//create and add "select users orders" query here...
First things first - Why this error? My SubSonic Users object knows it's PK. "uid" is the PK in the database and the generated code reflects this. And I thought SubSonicPrimaryKey attribute was for the SimpleRepository? Is this way of batching not for ActiveRecord?
I could ask a number of other questions, but I'll leave it at that. If anyone can help me figure out what is going on and how to issue 2 batched queries I'd be grateful!
Edit - after further investigation
I ran through the source code with the debugger. Adam is correct - the ToSchemaTable() method in Objects.cs is apparently building out my schema and failing to find a PK. At the very end, it tries to find a column property named "ID" and flags this as the PK, otherwise it throws the exception. I added a check for "UID" and this works!
Still... I'm confused. I'm admittedly a bit lost after peeling back layer after layer of the source, but it seems like this portion of code is trying to build up a schema for my table and completely ignoring my generated User class - which quite nicely identifies which column/property is the PK! It doesn't seem quite right that I'd be required to name all keys "ID" w/ ActiveRecord.
Comments
Something's wrong - did you use Structs.tt? Either that or it's been fixed (which could be) as FindOrCreate is the method that would cause the schema creator to go off. Structs.tt is the thing that adds your generated stuff to the Provider - same with Context.tt.
-
OldQuery tool: "*Join" Method generate invalid query (Fix inside)
1 comment Created 5 months ago by SettlerWhen I'm try to write somethig like this:
new Select().From().InnerJoin()
Query generate me this:
"select Table1.Id, Table2.Id from Table1,Table2 inner join Table2 on Table1.Id = Table2.Id" But this query not executed... Error is (for example, from MySQL): "Not unique table/alias: 'Table2'".I'f i'm rewrite query to this:
"select Table1.Id, Table2.Id from Table1 inner join Table2 on Table1.Id = Table2.Id", then all will be ok. So, for fix that issue, need to delete adding tables to "FROM" collection. This can be do in SqlQuery class: Old:private void CreateJoin(IColumn fromColumn, IColumn toColumn, Join.JoinType type) { Join j = new Join(toColumn, fromColumn, type); Joins.Add(j); //add the tables to the From collection if(!FromTables.Contains(toColumn.Table)) FromTables.Add(toColumn.Table); }New:
private void CreateJoin(IColumn fromColumn, IColumn toColumn, Join.JoinType type) { Join j = new Join(toColumn, fromColumn, type); Joins.Add(j); }Comments
-
System.NotSupportedException: The member 'Days' is not supported.
2 comments Created 5 months ago by dswatikTrying to do this query and getting a NotSupported Error
DateTime endDate = DateTime.Now; return (from members in Member.All() where endDate.Subtract(members.RemindedLast).Days > NumDays select members).ToList();and I keep getting
System.NotSupportedException: The member 'Days' is not supported.
Here is my stack trace... This works fine using LinqToSql so not sure what is missing in SubSonic
SubSonic.Linq.Structure.TSqlFormatter.VisitMemberAccess(MemberExpression m) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 216
SubSonic.Linq.Structure.ExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExpressionVisitor.cs: line 70
SubSonic.Linq.Structure.DbExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbExpressionVisitor.cs: line 60
SubSonic.Linq.Structure.TSqlFormatter.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 133
SubSonic.Linq.Structure.TSqlFormatter.VisitValue(Expression expr) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 850
SubSonic.Linq.Structure.TSqlFormatter.VisitBinary(BinaryExpression b) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 699
SubSonic.Linq.Structure.ExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExpressionVisitor.cs: line 60
SubSonic.Linq.Structure.DbExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbExpressionVisitor.cs: line 60
SubSonic.Linq.Structure.TSqlFormatter.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 133
SubSonic.Linq.Structure.TSqlFormatter.VisitPredicate(Expression expr) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 832
SubSonic.Linq.Structure.TSqlFormatter.VisitSelect(SelectExpression select) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 1023
SubSonic.Linq.Structure.DbExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbExpressionVisitor.cs: line 34
SubSonic.Linq.Structure.TSqlFormatter.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 133
SubSonic.Linq.Structure.TSqlFormatter.Format(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlFormatter.cs: line 37
SubSonic.Linq.Structure.TSqlLanguage.Format(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\TSqlLanguage.cs: line 52
SubSonic.Linq.Structure.ExecutionBuilder.ExecuteProjection(ProjectionExpression projection, Boolean okayToDefer) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExecutionBuilder.cs: line 217
SubSonic.Linq.Structure.ExecutionBuilder.VisitProjection(ProjectionExpression projection) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExecutionBuilder.cs: line 193
SubSonic.Linq.Structure.DbExpressionVisitor.Visit(Expression exp) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbExpressionVisitor.cs: line 54
SubSonic.Linq.Structure.ExecutionBuilder.Build(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExecutionBuilder.cs: line 46
SubSonic.Linq.Structure.ExecutionBuilder.Build(QueryPolicy policy, Expression expression, Expression provider) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\ExecutionBuilder.cs: line 41
SubSonic.Linq.Structure.QueryPolicy.BuildExecutionPlan(Expression projection, Expression provider) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\QueryPolicy.cs: line 102
SubSonic.Linq.Structure.DbQueryProvider.GetExecutionPlan(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbQueryProvider.cs: line 171
SubSonic.Linq.Structure.DbQueryProvider.Execute(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\DbQueryProvider.cs: line 117
SubSonic.Linq.Structure.QueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\QueryProvider.cs: line 50
GetEnumerator() in C:\Users\Dan\Documents\Development\SubSonic\SubSonic.Core\Linq\Structure\Query.cs: line 85
ctor(IEnumerable1 collection)<br/> System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
Daimokuchart.Model.MemberRepository.GetMembersToNotify(Int32 NumDays) in E:\Documents\Development\Daimokuchart\Daimokuchart.Model\Repositories\MemberRepository.cs: line 27
Daimokuchart.Web.Tests.MemberRepositoryTest.GetMembersToNotify_Should_Return_Members() in E:\Documents\Development\Daimokuchart\Daimokuchart.Web.Tests\Repository\MemberRepositoryTest.cs: line 86
Comments
I get the identical issue in a similar scenario after making some minor changes to ActiveRecord.tt to return List instead of IQueryable
-
Hi,
When you call ExecuteDataSet() Method from StoredProcedure you will
get the below error.The SelectCommand property has not been initialized before calling 'Fill'.
To resolve the issue we need to add one line in DbDataProvider.cs Class in ExecuteDataSet Method.
using(AutomaticConnectionScope scope = new AutomaticConnectionScope (this))
{ cmd.Connection = scope.Connection; AddParams(cmd, qry); DbDataAdapter da = Factory.CreateDataAdapter(); da.SelectCommand = cmd; //Add this line da.Fill(ds); return ds; }If it is not added into the project please add it.
Comments
-
Linq Templates - Update NullReferenceExpcetion
1 comment Created 5 months ago by bradleachI am using Subsonic v3.0.0.3 with the Linq templates. I am attempting to update a record in a SQL Server Express database with the following:
var db = new MyDB(Constants.Database);
db.Update()
.Set(d => d.FirstName == contact.FirstName) .Where(d => d.Id == contact.Id) .Execute(); I am receiving a NullReferenceException when this line is executed. The stack trace is as follows:at SubSonic.Query.Update.GetCommand() at SubSonic.Query.Update.Execute()
Comments
-
Linq Templates - Update NullReferenceExpcetion
1 comment Created 5 months ago by bradleachI am using Subsonic v3.0.0.3 with the Linq templates. I am attempting to update a record in a SQL Server Express database with the following:
var db = new MyDB(Constants.Database);
db.Update()
.Set(d => d.FirstName == contact.FirstName) .Where(d => d.Id == contact.Id) .Execute(); I am receiving a NullReferenceException when this line is executed. The stack trace is as follows:at SubSonic.Query.Update.GetCommand() at SubSonic.Query.Update.Execute()
Comments
-
Errors while saving a record if field name is the same as table name.
4 comments Created 5 months ago by aibatalovIf field of the table has the same name as table has, value of this field will never saved. It's not so critical, because often we can simply rename a field, but sometimes it's a bad surprise.
Comments
Hi aibatalov, I think I have fixed this bug, please check my Subsonic3 templates fork especially ActiveRecord/ActiveRecord.tt
I'm not think, that bug is in Templates... For example:
I'm have Table "Test". And Columns: "Id", "Test". So, when template was generated, column "Test" will be named as "TestX". This will be a name of property.So, when I'm create new entity, flag "isLoaded" is false. I'm fill this new entity:
Test test = new Test{TestX = "some text here"};And save:
test.Save();
So, when Save method is called, start working SubSonic.Core. There entity will be transformated to dictionary with property names and values of those properties. And after transfrom start generate query... It is ToInsertQuery method:public static ISqlQuery ToInsertQuery(this T item, IDataProvider provider) where T : class, new()
{ Type type = typeof(T); ITable tbl = provider.FindOrCreateTable<T>(); Insert query = null; if(tbl != null) { var hashed = item.ToDictionary(); query = new Insert(provider).Into<T>(tbl); ; foreach(string key in hashed.Keys) { IColumn col = tbl.GetColumn(key); if(col != null) { if(!col.AutoIncrement) query.Value(col.QualifiedName, hashed[key], col.DataType); } } } return query; }Here we have "key" field and it will be "TestX"... And tbl.GetColumn(key) will fail get this column, because "TestTable" don't have column "TestX"... And here is a bug, I'm think.
I do some changes with these. Please check my branch at http://github.com/funky81/SubSonic-3.0/commit/d73482c27d46602cbd105344ca28c4516c3c5d30
Hope it helps...
-
ActivRecord - tinyint converted to Boolean in SqlServer.ttinclude
1 comment Created 5 months ago by awbackerIt appears that tinyints are being handled inconsistently by SQLServer.ttinclude for ActiveRecord.
In GetSysType() "tinyint" falls through to boolean In GetDbType() "tinyint" converts to DBType.ByteChanging GetSysType() to this fixed it for me:
case "tinyint": sysType= "byte"; break;Comments
-
Hello,
When we try to execute linq like this:
from a in t1.All()
inner join b in t2.() on a.id equals b.id
inner join c in t3.All() on c.id equals b.id
select a;We get error:
"Don't know which column to join to - tried to join based on Primary Key id but couldn't find a match"The problem raises in SQLQuery class in routine: CreateJoin(string fromColumnName, string toColumnName, Join.JoinType type).
When I do step by step execution I see that the required relationship table has index 1 insted of predefined 0:
var fromColumn = FromTables[0].GetColumn(fromColumnName)Comments
-
After executing .tt files using MySql template, the class context.css was generated with errors in section 'Schemas'. The code generated is something like this:
DataProvider.Schema.Tables.Add(new citytownTable(DataProvider));where citytownTable is a table from my particular database, but the compiler says: ...missing reference or namespace...
i´ve tried to check inside the provider with not results.
Comments
I think this bug need to be posted here: http://github.com/subsonic/SubSonic-3.0-Templates/issues.
>Yes, in MySQL referenced tables stored in lower case. Our team modify MySQL.ttinclude. You can try to replace it with this:
<#@ include file="Settings.ttinclude" #> <#@ assembly name="MySql.Data" #> <#@ import namespace="MySql.Data.MySqlClient" #> <#+ const string FKSql=@"SELECT C.TABLE_NAME as ThisTable, C.COLUMN_NAME as ThisColumn, (SELECT DISTINCT FC.TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE FC WHERE LOWER(C.REFERENCED_TABLE_NAME) = LOWER(FC.TABLE_NAME)) as OtherTable, C.REFERENCED_COLUMN_NAME as OtherColumn, C.CONSTRAINT_NAME as Constraint_Name, C.TABLE_SCHEMA as Owner FROM information_schema.KEY_COLUMN_USAGE C WHERE (C.REFERENCED_TABLE_SCHEMA = '{0}' AND C.REFERENCED_TABLE_NAME ='{1}' AND C.TABLE_NAME is not null ) OR (C.TABLE_SCHEMA = '{2}' AND C.TABLE_NAME ='{3}' AND C.REFERENCED_TABLE_NAME is not null ) ORDER BY C.TABLE_NAME, C.COLUMN_NAME;"; MySqlConnection conn; MySqlCommand GetCommand(string sql){ MySqlConnection conn=new MySqlConnection(ConnectionString); MySqlCommand cmd=new MySqlCommand(sql,conn); conn.Open(); return cmd; } ListLoadTables(){ var result=new List
(); using(conn=new MySqlConnection(ConnectionString)){ conn.Open(); //this will return everything for the DB var schema = conn.GetSchema("COLUMNS"); conn.Close(); //spin through once to get all the tables foreach (DataRow row in schema.Rows) { if(!result.Any(x=>x.Name.Equals(row["TABLE_NAME"].ToString(),StringComparison.InvariantCultureIgnoreCase))) { //add it Table tbl = new Table(); tbl.PrimaryKey=""; tbl.Name = row["TABLE_NAME"].ToString(); tbl.Schema = row["TABLE_SCHEMA"].ToString(); tbl.FKTables=LoadFKTables(tbl.Name); tbl.CleanName=CleanUp(tbl.Name); tbl.ClassName=Inflector.MakeSingular(tbl.CleanName); tbl.QueryableName=Inflector.MakePlural(tbl.ClassName); result.Add(tbl); } } //loop again - but this time pull by table name foreach (var item in result) { item.Columns=new List(); //pull the columns from the schema var columns = schema.Select("TABLE_NAME='" + item.Name + "'"); foreach (var row in columns) { Column col=new Column(); col.Name=row["COLUMN_NAME"].ToString(); col.CleanName=CleanUp(col.Name); col.DataType=row["DATA_TYPE"].ToString(); col.SysType=GetSysType(col.DataType); col.DbType=GetDbType(col.DataType); col.AutoIncrement=row["EXTRA"].ToString()=="auto_increment"; col.IsNullable=row["IS_NULLABLE"].ToString()=="YES"; col.IsPK=row["COLUMN_KEY"].ToString()=="PRI"; if(col.IsPK){ item.PrimaryKey=col.Name ?? ""; } int.TryParse(row["CHARACTER_MAXIMUM_LENGTH"].ToString(),out col.MaxLength); item.Columns.Add(col); } } foreach(Table tbl in result){ //loop the FK tables and see if there's a match for our FK columns foreach(Column col in tbl.Columns){ col.IsForeignKey=tbl.FKTables.Any( x=>x.ThisColumn.Equals(col.Name,StringComparison.InvariantCultureIgnoreCase) ); } } } return result; } List LoadFKTables(string tableName){ //this is a "bi-directional" scheme //which pulls both 1-many and many-1 var result=new List(); var cmd=GetCommand(string.Format(FKSql, DatabaseName, tableName, DatabaseName, tableName)); //cmd.Parameters.AddWithValue("@tableName",tableName); using(IDataReader rdr=cmd.ExecuteReader(CommandBehavior.CloseConnection)){ while(rdr.Read()){ FKTable fk=new FKTable(); string thisTable=rdr["ThisTable"].ToString(); if(tableName.ToLower()==thisTable.ToLower()){ fk.ThisTable=rdr["ThisTable"].ToString(); fk.ThisColumn=rdr["ThisColumn"].ToString(); fk.OtherTable=rdr["OtherTable"].ToString(); fk.OtherColumn=rdr["OtherColumn"].ToString(); }else{ fk.ThisTable=rdr["OtherTable"].ToString(); fk.ThisColumn=rdr["OtherColumn"].ToString(); fk.OtherTable=rdr["ThisTable"].ToString(); fk.OtherColumn=rdr["ThisColumn"].ToString(); } fk.OtherClass=Inflector.MakeSingular(CleanUp(fk.OtherTable)); fk.OtherQueryable=Inflector.MakePlural(CleanUp(fk.OtherTable)/*fk.OtherClass*/); result.Add(fk); } } return result; } string GetSysType(string sqlType){ string sysType="string"; switch (sqlType) { case "bigint": sysType= "long"; break; case "int": sysType= "int"; break; case "smallint": sysType= "short"; break; case "guid": sysType= "Guid"; break; case "smalldatetime": case "date": case "datetime": case "timestamp": sysType= "DateTime"; break; case "double": case "float": sysType="double"; break; case "real": case "numeric": case "smallmoney": case "decimal": case "money": sysType= "decimal"; break; case "tinyint": case "bit": sysType= "bool"; break; case "image": case "binary": case "varbinary": sysType= "byte[]"; break; } return sysType; } DbType GetDbType(string sqlType){ switch(sqlType) { case "varchar": return DbType.AnsiString; case "nvarchar": return DbType.String; case "integer": return DbType.Int32; case "guid": return DbType.Guid; case "date": case "timestamp": case "datetime": return DbType.DateTime; case "bigint": return DbType.Int64; case "binary": return DbType.Binary; case "bit": return DbType.Boolean; case "char": return DbType.AnsiStringFixedLength; case "decimal": return DbType.Decimal; case "double": case "float": return DbType.Double; case "image": return DbType.Binary; case "money": return DbType.Currency; case "nchar": return DbType.String; case "longtext": return DbType.String; case "numeric": return DbType.Decimal; case "real": return DbType.Single; case "smalldatetime": return DbType.DateTime; case "smallint": return DbType.Int16; case "smallmoney": return DbType.Currency; case "sql_variant": return DbType.String; case "sysname": return DbType.String; case "text": return DbType.AnsiString; case "tinyint": return DbType.Byte; case "varbinary": return DbType.Binary; default: return DbType.AnsiString; } } #>
I replaced the file, and run the process again but still getting the same error:
region ' Schemas '
if(DataProvider.Schema.Tables.Count == 0) { DataProvider.Schema.Tables.Add(new citytownTable(DataProvider)); DataProvider.Schema.Tables.Add(new countryTable(DataProvider)); } #endregionthe 'citytownTable' and 'countryTable' are not valid types. I still receive an error about missing reference or directive ...
thanks a lot.
Are you run process in Structs.tt file? Because for class names there and in Context.tt used same names. Or what names for tables you have in Structs.xx generated file?
We found a nasty bug today when updating to the new version and not the alpha one we had been using. It seems that the method:
public virtual IEnumerable Execute(QueryCommand query, object[] paramValues)
inside of DBQueryProvider on line 266 and below this comment:
////this is so hacky - the issue is that the Projector below uses Expression.Convert, which is a bottleneck
////it's about 10x slower than our ToEnumerable. Our ToEnumerable, however, stumbles on Anon types and groupings ////since it doesn't know how to instantiate them (I tried - not smart enough). So we do some trickery here.The problem is that when we are running this kind of query:
var divisions =
from org in db.Groups join sport in db.Groups on org.Id equals sport.GroupId join season in db.SportSeasons on sport.Id equals season.SupportedSportId join sd in db.SeasonalDivisions on season.id equals sd.SportSeasonId join division in db.Groups on sd.DivisonId equals division.Id select new Division() { Id = division.Id, Name = division.Name, SeasonId = season.id, SeasonName = season.Name, SportId = sport.Id, SportName = sport.Name, OrganizationId = org.Id, IsRetired = division.IsRetired.GetValueOrDefault() };which we have in a lot of places, it fails, so I just commented out the lines of code below the comment, but I would like to understand the enhancement this creates before I write a breaking test to make sure these kind of queries will work in the future and if I need to make a patch to make my query work with the optimization or just comment out the optimazation so that these queries will work in the future.
Comments
SubSonic MVC template ported to release. Edit issue.
4 comments Created 5 months ago by fdeHi Rob,
I've migrated my test project created using SubSonic MVC template.
Everything working fine with minor changes except the update operation.
We have the next code as a result of T4 work:
if(ModelState.IsValid){ string resultMessage = ""; try { _repository.Update(item); resultMessage = item.DescriptorValue() + " updated!"; } catch(Exception x) { //edit this to return a message resultMessage = "ERROR: "+ item.DescriptorValue() + " failed: "+x.Message; } //if this is an Ajax request - just send back a message if (Request.IsAjaxRequest()) { return Content(resultMessage); } else { return RedirectToAction("Index"); } }The exception takes place in _repository.Update(item); line. The message "Incorrect syntax near the keyword 'WHERE'."
I've figured out that the this line generates the UPDATE SQL command without SET sentances.
The item.update(); works well.
I haven't a chance to take a look into source code using debugger yet. But I'll try.
Thanks,
Dmitry.Comments
I came across this and its because you probably have model binding in your controller action Edit(int ID, Person p). Because the model binder has used reflection it therefore is a new instance and has no dirty columns to process in the repo.Update call. You have to change it to Edit(int ID, FormCollection coll) and then do Person p = Person.SingleOrDefault(x => x.ID == ID); TryUpdateModel(p, coll.ToValueProvider())
I had this discussion with Rob quite a while ago on the Subsonic Google forums
Thanks for the answer. It's clear for me why it doesn't work as it should.
Unfortunately I didn't find the discussion you are refferenced to. May be it has the answers to my questions.
1) The alpha had worked well. May be it could be interesting to fix this point?
2) Why the item.update() work in this case fine? It shouldn't have dirty columns too.
3) Is it interesting to update MVC Starter Template up to the release of the Subsonic?Thanks,
Dmitry.Is Transactions working in SubSonic 3.0 and MySQL?
8 comments Created 5 months ago by SettlerI'm try to use transactions for saving entities and references in one transaction. But my transactions are not working...
What I'm do:
.......try
{ using (SharedDbConnectionScope sharedConnectionScope = new SharedDbConnectionScope()) { using (TransactionScope ts = new TransactionScope()) { Test test = new Test(); test.Name = "name"; test.Save(); SaveReferences(test); ts.Complete(); } } } catch(Exception ex) { throw ex; }......
private void SaveReferences(Test test)
{throw new Exception("Test must be not saved here");}
where Test - is IActiveRecord.
I'm do somethig wrong?
(SubSonic 3.0.0.3, Windows XP SP3)Comments
And more... If I'm use this transaction mechanism, then I'm catch exception in ExecuteQuery of DbDataProvider: "There is already an open DataReader associated with this Connection which must be closed first.", when save many entities in TransactionScope.
carlosklein
Mon Jul 20 06:51:51 -0700 2009
| link
Same problem:
http://stackoverflow.com/questions/1143409/subsonic-transaction-error/1144198#1144198Can you try the use the BatchUpdate alternative to see if you get the same errors of this issue? http://github.com/subsonic/SubSonic-3.0/issues#issue/60
I'm comment your issue, but BatchUpdate is not better way for me, because in method SaveReferences can be saved many types of data in different tables. Or there can be called other methods for save. And if I'm will use BatchUpdate tool, then I need to create it in head method and transfer to SaveReferences. And there it need to be transfered in other methods... Not beauty, I think. All my problems will be resolved, if TransactionScope style is start working...
carlosklein
Tue Jul 21 06:14:16 -0700 2009
| link
Same here.
I'm having the same problem with SQL 2008. BatchQuery is less than optimal as I have to get generated IDs of some of the items in the transaction to populate others.
I believe I've fixed it. The bug occurs when you are using ActiveRecord and are also inserting items in the transaction. When this occurs, the SubSonicRepository.Add(T item, IDataProvider provider) method is invoked, which returns the newly inserted item's primary key by using a DataReader - which is not closed before the method exits; thus the error about a reader being open.
Changing line 197 in SubSonicRepository.cs (3.0.0.3) to "using (DbDataReader rdr = provider.ExecuteReader(query))" (and wrapping the using in an appropriate scope to about like 218) seems to have solved it for me.
BatteryMan
Thu Aug 20 22:07:37 -0700 2009
| link
Kamsar's solution seems to have made it into the 2009-08-18 commit. However, I am still experiencing the problem originally described by Settler, though I am using MS SQL 2005 Express Edition.
Anyone else still having problems? Thanks.
projection looking at name only and not typename
1 comment Created 5 months ago by subnusas discussed in
http://groups.google.com/group/subsonicproject/browse_thread/thread/2b569539b7f67a34?hl=en
Comments
String comparisons in LINQ break under VB.NET
3 comments Created 5 months ago by BlackMaelSubSonic throws an exception when LINQ query contains a string comparison from VB.NET code.
VB.NET generates different expression than C# for string comparisons. It uses a special CompareString operator.
Comments
See http://blogs.msdn.com/vbteam/archive/2007/09/18/vb-expression-trees-string-comparisons.aspx for explanation and solution.
I have implemented the fix in SubSonic myself. Just need to merge it into the solutionDim result = From c In Customer.All() _ Where String.Equals(c.ContactName, contactName) _ Select c myCustomer = result.FirstOrDefaultAlso broke which required a little more work. I have a fix but not sure if it is the best solution
ActiveRecort - dirty columns not cleared on update()
1 comment Created 5 months ago by awbackerThe dirtyColumns are not being cleared by the Update() method. This means that the object is is still reported as IsDirty after the changes have been committed to the database.
Currently we have this:
if (this._dirtyColumns.Count > 0) { _repo.Update(this, provider);Something along these lines would fix that up:
if (this._dirtyColumns.Count > 0) { _repo.Update(this, provider); _dirtyColumns.Clear(); }Comments
I'm not on the machine where I can fix this right now. This line: http://github.com/subsonic/SubSonic-3.0/blob/0f6248f9ee1e30287140932ca051e1992c70da0d/SubSonic.Core/Query/Update.cs#L230
Has an extra ; that's forcing the next line to run every time, instead of only when the condition is met.
Comments
Thanks John... Fixed... Commit coming in a few minutes...
johnsheehan
Tue Jul 21 21:47:48 -0700 2009
| link
Thanks Eric
<IQueryable>.Skip() method does not return values
2 comments Created 5 months ago by tringHello,
I created a very simple Linq:
var result = (from p in Customers.All()
select p).Skip(1);but it does not return any values from database. When I try with Take() it works?
Issue or...
Comments
I have posted a number of scenarios when trying to do something to replicate a DELETE FROM TABLE WHERE COLUMN NOT IN (1,2,3) on stackoverflow.
http://stackoverflow.com/questions/1136415/reproduce-a-delete-not-in-sql-statement-via-linq-subsonic
My last attempt to do a Class.Delete(lamda threw an exception) as you will see in the post.
Comments
SimpleRepository Fail to Map Property of type Boolean (or bool) to SQLite
6 comments Created 5 months ago by cfdelauneWhen I create an object with a Property of type Boolean (or bool) and use SimpleRepository to map it to SQLite, the column gets successfully created, but upon retrieval of the data, the following error gets thrown:
"Object of type 'System.Byte' cannot be converted to type 'System.Boolean'."
I posted this question on StackOverFlow and got an answer that I think might mean this is a bug. Here is my post:
http://stackoverflow.com/questions/1137649/simplerepository-boolean-mapping-problem
Basically, in the SQLiteSchema.cs file, in the GetNativeType(DbType dbType) method, it looks like in the case of DbType.Boolean, the type was being set as "tinyint". I checked this and indeed, the column in my SQLite database was of type "tinyint". I changed this to "boolean", recompiled SubSonic and that seems to have resolved the problem.
Thanks!
Comments
For SQL Server at least, I found this is an issue with the GetSysType() function in SQLServer.ttinclude. The "case 'tinyint':" falls through to the bit/boolean conversion. Changing it to this fixed it for me:
case "tinyint": sysType= "byte"; break;This is fixed (for sql server, and maybe sqlite) int the latest build.
If I have the tinyint/byte/bool discussion again, I'm going to lose it. Closing - this is a recursive bug....
I don't see the problem. This issue was posted ages ago, so it isn't really "again". It got fixed (in sql from an issue submitted by me, dunno about sqlite). Any special sauce we can provide for relaxation and restoration of your sanity?
To be fair... you did ask the this person to open the issue when he/she raised it in stackoverflow.
http://stackoverflow.com/questions/1137649/simplerepository-boolean-mapping-problem
Considering the following code:
var query2 = new Update<BoletoPagamento>(provider); query2.Set(x => x.DataLiberacao == boleto.DataLiberacao); query2.Where(x => x.BoletoPagamentoID == boleto.BoletoPagamentoID); batch.Queue(query2); batch.Execute();The batch.Execute() trown an "Object Reference Not Set" exception. Investigating, I arrived at the following line of the file Subsonic.core\Query\Update.cs, method GetCommand():
var col= table.Columns.SingleOrDefault(x => x.Name.Equals(s.ColumnName, StringComparison.InvariantCultureIgnoreCase));My column was in table.Columns but s.ColumnName was filled with
`DataLiberacao`This prevented the location of the column and resulted in null object reference set. I do not know how to fix it.
Then i tried to use the old style query tool:
SubSonic.Query.Update query = new Update<BoletoPagamento>(provider); query.Set("DataLiberacao").EqualTo(boleto.DataLiberacao); batch.Queue(query); batch.Execute();In this case, the Subsonic build a command to update with an "s" at the end of the table name. Instead of "Update BoletoPagamento," was "BoletoPagamentos" and table "BoletoPagamentos" does not exist.
In the source SubSonicCore\Extensions\Object.cs, method ToSchemaTable(this Type type, IDataProvider provider): In this method, my tablename is modified with "tableName = tableName.MakePlural();".Then I tried a simple Save () in my BoletoPagamento object, the command is generated correctly, without the "s" at the end of the table name.
But, as I need to save several objects of this type, this is not a good ideia and another problem doing this: the subsonic not reuse the connection to the database, opening an connection for each object.I am using the 3.0.0.3 sources, windows Vista, VS2008 and MySql.
Comments
Well. The LINQ Query tool not working for me too. Because s.ColumnName - is full name of column in database i think... Like: 'DBName'.'TableName'.'ColumnName'.
Old query style is working. I think you're not properly get "provider". I'm store provider in static variable. And initialize it like this:
protected static IDataProvider provider = new TestDB().Provider;
Where TestDB - is generated class from Context.tt
Damn!!! :) :) :)
Check this block of code in public QueryCommand GetCommand() in Update class:if (table != null) {
var col= table.Columns.SingleOrDefault(x => x.Name.Equals(s.ColumnName, StringComparison.InvariantCultureIgnoreCase)); if (col != null) ; s.DataType = col.DataType; }And check the "if" statment. There is !!!!! " ; " !!!!! at the end of line :) Very nasty bug :) But, i think, this is not solve the problem, because "col" will be always null.
carlosklein
Tue Jul 21 06:04:39 -0700 2009
| link
Its Grave Accent fault. In debug mode, if i cut the accent, works.
The old query style its not working because i use this code to correct table names in the method CleanUp of Setting.ttinclude (ex: table name = agendamento_horario, corrected name = AgendamentoHorario.)
string[] parts = result.Split('_'); string tabela = String.Empty; foreach(String part in parts) { tabela += part.Substring(0,1).ToUpper() + part.Substring(1,part.Length -1); } result = tabela;Probably, there is a problem there too.
Active Record Lamda Expression Issue with String Array value
1 comment Created 5 months ago by jchannonI have the following:
var contentdata = value.Split(',');
//contentdata contains 2 items//Find item using contentdata[0] WebPageContent item = new WebPageContent(x => x.PageID == ID && x.ControlType == contentdata[0]);
Error thrown in SQLQuery::Where method As it loops through constraints it thinks a the column name is called contentdata.
I can fix it by doing this:
string sitem = contentdata[0];
WebPageContent item = new WebPageContent(x => x.PageID == ID && x.ControlType == sitem);Not sure what the difference is!
Comments
the linq statement doesnt find a column so i changed x.Name to x.QualifiedName and it seemed to fix it for me!?!?
public QueryCommand GetCommand() {
QueryCommand cmd = new QueryCommand(BuildSqlStatement(), _provider); //add in the commands foreach (Setting s in _query.SetStatements) { //Fix the data type! var table = _query.FromTables.FirstOrDefault(); if (table != null) { var col= table.Columns.SingleOrDefault(x => x.QualifiedName.Equals(s.ColumnName, StringComparison.InvariantCultureIgnoreCase)); if (col != null) s.DataType = col.DataType; } cmd.Parameters.Add(s.ParameterName, s.Value, s.DataType); } //set the contstraints _query.SetConstraintParams(cmd); return cmd; }Comments
Yes, that worked. Release 3.0.0.3 seems to still have that ; on line if (col != null)
SubSonic.Core\Query\Update.cs
public QueryCommand GetCommand()
line 220Why did this issue get closed? It seems to still be a bug with the current version of the source.
Chanding "Name" to "QualifiedName" in GetCommand() does the trick. I tried it on SQLite.
Is this the way to fix it?Using 3.0.2
My class:
public class Conta
{ public int ContaID { get; set;} public string Nome { get; set; } public bool Publica { get; set; } }The code:
_repo = new SimpleRepository("Contas", SimpleRepositoryOptions.RunMigrations);
var contas = _repo.All<Conta>(); return View(contas);The Error:
Object of type 'System.Int64' cannot be converted to type 'System.Int32'.
Works if i declare ContaID as a Int64
Works fine with Sql Server.Comments
ActiveRecord lambda expression partially ignored on delete
1 comment Created 5 months ago by gbdI have tables Users, Widgets and Layouts. Users have many-to-many relationship with Widgets via Layouts. Each Layout has
UserIDandWidgetID. I want to delete a Layout that matches specificUserIDandWidgetID.Using SubSonic 3 ActiveRecord I write:
Layout.Delete(x => x.UserID == user.id && x.WidgetID == id);However, SubSonic deletes all widget layouts for the user, ignoring the second part of the condition.
I fixed it temporarily in Context.tt in my project's Models subdirectory:
diff --git a/Models/Context.tt b/Models/Context.tt index ee64200..dd47510 100644 --- a/Models/Context.tt +++ b/Models/Context.tt @@ -162,8 +162,8 @@ namespace <#=Namespace#> LambdaExpression lamda = column; SqlQuery result = new Delete<T>(this.Provider); result = result.From<T>(); - SubSonic.Query.Constraint c = lamda.ParseConstraint(); - result.Constraints.Add(c); + var q = new QueryVisitor(); + result.Constraints.AddRange(q.GetConstraints(lamda)); return result; }Comments
This method works fine:
Person p = new Person(3);
p.Name = "Bob";
p.Update();However if I have an IQueryable foreign key collection the below fails
var foreignItems = Person.Find(x => x.ID == 3)
foreach(Person p in foreignItems)
{ p.Name = "Bob"; p.Update(); /THROWS EXCEPTION / }Exception is thrown in Repository Update as it executes a query from BuildUpdateQuery such as - UPDATE PERSON WHERE ID = {0} which is wrong syntax!
Comments
Using ActiveRecord templates on updating record with a date field causes exception: [SqlException (0x80131904): The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.The statement has been terminated.]
Based on this question from stackoverflow
http://stackoverflow.com/questions/1124670/datetime-fields-updates-cause-exceptionHere is the schema
CREATE TABLE [dbo].[stPost]( [postID] [int] IDENTITY(1,1) NOT NULL, [postGuid] [uniqueidentifier] NOT NULL, [postCreatedDate] [datetime] NOT NULL, [postUpdatedDate] [datetime] NOT NULL, [postTitle] [nvarchar](50) COLLATE Cyrillic_General_CI_AS NOT NULL, [postDescription] [nvarchar](max) COLLATE Cyrillic_General_CI_AS NOT NULL, [deleted] [bit] NOT NULL CONSTRAINT [DF_stPost_deleted] DEFAULT ((0)), CONSTRAINT [PK_stPost] PRIMARY KEY CLUSTERED ( [postID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]And here is a test
DateTime currentDateTime = DateTime.Now; currentDateTime = new DateTime(currentDateTime.Ticks - (currentDateTime.Ticks % TimeSpan.TicksPerSecond), currentDateTime.Kind); stPost post = new stPost(); post.postCreatedDate = currentDateTime; post.postDescription = "cool post at " + currentDateTime.ToString(); post.postGuid = Guid.NewGuid(); post.postTitle = "Post title"; post.postUpdatedDate = currentDateTime; post.Save(); post = new stPost(p => p.postID == post.postID); Assert.IsTrue(currentDateTime.Equals(post.postUpdatedDate)); DateTime updatedDateTime = DateTime.Now.AddMinutes(1); updatedDateTime = new DateTime(updatedDateTime.Ticks - (updatedDateTime.Ticks % TimeSpan.TicksPerSecond), updatedDateTime.Kind); post.postDescription = "cool post UPDATED at " + DateTime.Now.ToString(); post.postTitle = "Post title Updated"; post.postUpdatedDate = updatedDateTime; post.Save(); post = new stPost(p => p.postID == post.postID); Assert.AreEqual(updatedDateTime, post.postUpdatedDate);Comments
carlosklein
Wed Jul 15 06:59:14 -0700 2009
| link
The lastest source solved the problem for me.
Thanks. I just got latest sources and it's really fixed. :) I've been using 3.0.0.2 before and it was not working. I guess someone fixed this problem in the past few days.
When we are in read-only mode for browsing details click on "Edit" link causes exception
System.FormatException was unhandled by user code
Message="Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)."id is empty in the following code snippet
[AcceptVerbs(HttpVerbs.Get)] public ActionResult Edit(string id) { var postID = new Guid(id);Comments
When I add a column of type Bit (1) in a table, the querie hang when i call ToLit() Or .SingleOrDefault(). If I remove the column, everything returns to normal.
Comments
adamnoffie
Tue Jul 14 15:39:09 -0700 2009
| link
Wow. That it does not.
carlosklein
Tue Jul 14 19:05:16 -0700 2009
| link
I build a test project to reproduce the error.
In this case, I get an exception: Object of type 'System.UInt64' can not be converted to type 'System.Boolean'. In the sendspace link is the zipped project (the database is in an account of db4free.net, username and password in the app.config of the project). At work, instead of this error, the application simply stopped.Yes.
DB type -> .NET Type
BIT -> UInt64
BOOL -> SByteI hacked the source to "make it work". If the db type is TINYINT or BIT, and the property is typeof(Boolean), I .ToString() the value and compare with 1 or 0.
Hacked this in SubSonic.Core\Extensions\Database.cs:169, see the first "else if".
//if the property is null, likely it's a Field if(currentProp == null) currentField = cachedFields.SingleOrDefault(x => x.Name.Equals(pName, StringComparison.InvariantCultureIgnoreCase)); if(currentProp != null && !DBNull.Value.Equals(rdr.GetValue(i))) { Type valueType = rdr.GetValue(i).GetType(); if(valueType == typeof(Boolean)) { string value = rdr.GetValue(i).ToString(); currentProp.SetValue(item, value == "1" || value == "True", null); } else if (valueType == typeof(SByte) && currentProp.PropertyType == typeof(Boolean) && (rdr.GetDataTypeName(i).Equals("TINYINT", StringComparison.OrdinalIgnoreCase) || rdr.GetDataTypeName(i).Equals("BIT", StringComparison.OrdinalIgnoreCase)) ) { string value = rdr.GetValue(i).ToString(); currentProp.SetValue(item, value == "1", null); } else if (currentProp.PropertyType == typeof(Guid)) currentProp.SetValue(item, rdr.GetGuid(i), null); else currentProp.SetValue(item, rdr.GetValue(i).ChangeTypeTo(valueType), null); }Also related: http://github.com/subsonic/SubSonic-3.0/issuesearch?state=open&q=BOOL#issue/110
And a heads-up for this problem too: http://github.com/subsonic/SubSonic-3.0/issuesearch?state=open&q=BOOL#issue/111
Generated active records for vb got some errors
2 comments Created 5 months ago by tuanvtWhen adding files for generating active records for a vb project, all of the class in activerecord.vb missing "implements IActiveRecord.SetIsNew" in SetIsNew.
Generated:Public Sub SetIsNew(ByVal isNew As Boolean)
_isNew = isNew End SubShould be
Public Sub SetIsNew(ByVal isNew As Boolean) Implements IActiveRecord.SetIsNew _isNew = isNew End SubComments
Tuanvt See http://github.com/subsonic/SubSonic-3.0/issues#issue/42 for the fix
Can Sql 2005 data type "XML" be unicode string instead of ansi string
4 comments Created 5 months ago by ClarkKangSQL 2005 new data type "XML" is translate to ansi string. So, the unicode character cannot save back to SQL Server. It became "???" in the database.
Comments
A string is a string - what you're seeing, I think, has more to do with the file type encoding and how your DB handles it.
I think so at first time. But I try to insert data by QueryCommand, and set the parameter's data type as "DbType.XML". Then the data save to database correctly.
I can't find out where to modify the data type to DbType.XML.
Here is the string I try to save:<vcCustomer_Name>羅亦峻12</vcCustomer_Name>
OK I've added a DBType.Xml switch to SQLServer.ttinclude - pushing now.
Incorrect Order when using paging with order by
3 comments Created 5 months ago by ClarkKangWhen using paging and order by, the result of the query is in wrong order.
Is it possible to add order by "IndexId" to the sqlgenerator?Comments
I don't understand what you're asking and what "wrong order" means.
I figure it out. I'll try to explain it clearly.
1. The data type of the table's pk is "uniqueidentifier"
2. I create a view base on the table.
3. Using query object to query the view with paging and order byThe query will generate the sql like :
SELECT FROM #temp
WHERE _indexID BETWEEN ((@Page - 1) @PageSize + 1) AND (@Page * @PageSize)Because of the table's pk is a uniqueidentifier. So, without order by _indexID , the order of the result is unexpected.
I hope the information will help.
MySQL datetime format is: 'YYYY-MM-DD HH:MM:SS' or 'YY-MM-DD HH:MM:SS'
When I'm save entity of ActiveRecord template that have, for example, column ModifiedOn, then I catch exception: "Incorrect datetime value: '13.07.2009 11:56:45' for column 'ModifiedOn' at row 1", beacause DateTime.Now.ToString(), for default, give value in CurrentCulture (CurrentUICulture?) format... For Russian culture is: 'DD-MM-YYYY HH:MM:SS'.Comments
Try the latest source and see if this is fixed. I caught a couple of DbType errors in there.
carlosklein
Wed Jul 15 06:49:14 -0700 2009
| link
Nice! I was having the same problem here. Using the latest source, problem solved.
Hi, I am trying to transform the last tutorials of MVC into Subsonic 3.0 base in www.asp.net/MVC. When I edit an item and POST back to the Controller:
ContactController.cs
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Contact contactToEdit) { ValidateContact(contactToEdit); if (!ModelState.IsValid) return View(); try { // TODO: Add update logic here _repository.EditContact(contactToEdit); //return View(contactToEdit); return RedirectToAction("Index"); } catch { return View(); } }EntiryContactManagerRepository.cs
public Contact EditContact(Contact contactToEdit) { var contactMe = Contact.SingleOrDefault(x => x.Id == contactToEdit.Id); contactMe.FirstName = contactToEdit.FirstName; contactMe.LastName = contactToEdit.LastName; contactMe.Phone = contactToEdit.Phone; contactMe.Email = contactToEdit.Email; contactMe.Update(); return contactMe; //contactToEdit.Update(); //return contactToEdit; }I can't do the direct Update() from the POST back an "contact" that already contain an Id. so I need to do it in another repository class. Any idea about how to simplify it?
I love subsonic and I really want to see that doing with it is more simpler that doing with LINQToSql or entity framework.Comments
When I do it directly like this:
ContactController.cs
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Contact contactToEdit) { ValidateContact(contactToEdit); if (!ModelState.IsValid) return View(); try { // TODO: Add update logic here contactToEdit.Update(); //return View(contactToEdit); return RedirectToAction("Index"); } catch { return View(); } }It just don't work!
johnsheehan
Sun Jul 12 21:34:25 -0700 2009
| link
I think this is more a StackOverflow type question since there doesn't appear to be an issue with SubSonic to me. As far as your comment goes, "It just don't work!" is not a very complete picture of the problem. You need to explain what you expected to happen and what happened instead (error?).
That means I can't do an Update() in the active record method, the Update() doesn't work. When I click the Update button in the view, the “post” type "ActionResult Edit(Contact contactToEdit)" runs, the parameter class "contactToEdit" contain new values in its members being post back. But It seems that It's flaged IsNew or something. whenever I run it, it just do a new insert, but not an update operation. Yesterday I posted this issues When I was using 3.0.0.1, I did it in the first way it was still working. then I updated to 3.0.0.3, I found that the update() operation doesn't work anymore when ever I try:
var contactMe = Contact.SingleOrDefault(x => x.Id == contactToEdit.Id); contactMe.FirstName = contactToEdit.FirstName; contactMe.LastName = contactToEdit.LastName; contactMe.Phone = contactToEdit.Phone; contactMe.Email = contactToEdit.Email; contactMe.Update();or:
contactToEdit.Update();I don't understand the problem. Also - you should use "UpdateModel(contact)" to avoid the left/right stuff.
When you say "doesn't work" - what do you mean?
I finally found that was my own mistake in my code to use repository pattern. During the test I copied and pasted the code and forgot to changed it to "EditContact"
_repository.CreateContact(contactToEdit);So whenever I try to changed the code in the EditContact itself, it just didn't work, it calls the CreateContact instead ...
Thanks Rob! The "UpdateModel" helps me a lot! I'm learning MVC with subsonic. I was thinking that Subsonic must have this kind of method, but when I tried the Update() method it doesn't appear to be what I want.I think the best practice is the fastest develop speed in small projects!
By the way, where's the class document in subsonicproject.com, I can't find that.
Make it easy to override GetHashCode implementation
2 comments Created 5 months ago by WillSullivanI've heard a couple people complain about the hashcode implementation in the T4 templates. I've got a workaround that would allow people to easily override the implementation via partial classes and partial methods without having to extend the data models.
Here's some sample code that illustrates how to do this:
public partial class Foo { public override int GetHashCode() { int? result = null; TryGetHashCode(ref result); if (result.HasValue) return result.Value; return new Random().Next(); } partial void TryGetHashCode(ref int? result); } public partial class Foo { partial void TryGetHashCode(ref int? result) { result = 5; } }If you don't create a partial class for Foo, or if your partial class doesn't provide an implementation of Foo, then execution of the default hashcode executes and the result is returned. Simply providing the partial class with the implementation will override the default implementation. You already know the benefits of using partial classes when dealing with generated code.
Comments
I think, GetHashCode override can be implemented in T4 template of ActiveRecord like this:
public override int GetHashCode() { if(!isNew && KeyValue() != null) { return KeyValue().GetHashCode(); } return base.GetHashCode(); }
WillSullivan
Mon Jul 13 06:22:25 -0700 2009
| link
It essentially is. But that is going to rely on the framework's implementation of the hashing function for pretty much any key value you have, which is NOT a good thing. A better implementation would hash it against the other state of the active record and return the result. If a developer needs a good hash code implementation they're going to have to do it themselves; it would be near impossible for a T4 to be dead on every time.
Version 3.0.0.2
I'm create basic interface, that help me create base classes for all entities. Here it is:
////// A basic record interface /// </summary> public interface IBasicRecord : IActiveRecord { long Id { get; set; } }In ActiveRecord.tt almost all my classes implement IBasicRecord. For example:
public partial class Test : IBasicRecord
{ ....private long idDbColumn; public long Id { get { return idDbColumn; } set { idDbColumn = value; var col=tbl.Columns.SingleOrDefault(x=>x.Name == "Id"); if(col!=null) { if(!dirtyColumns.Any(x=>x.Name == col.Name) && isLoaded) { dirtyColumns.Add(col); } } OnChanged(); } }.... }
So, when I'm type code like this:
Test test = (new SubSonicRepository (new MyDB())).GetAll().SingleOrDefault(o => o.Id == entityId);
Everything work fine, but if I'm write:public class Helper where T : IBasicRecord, new()
{public T GetById(entityId) { T test = (new SubSonicRepository<T>(new MyDB())).GetAll().SingleOrDefault(o => o.Id == entityId); }}
then I'm catch NotSupportedException. I'm do something wrong?
Comments
Well. I'm fix this problem by changing method private static bool MembersMatch(MemberInfo a, MemberInfo b) of QueryBinder class from:
private static bool MembersMatch(MemberInfo a, MemberInfo b) { if (a == b) { return true; } if (a is MethodInfo && b is PropertyInfo) { return a == ((PropertyInfo) b).GetGetMethod(); } if (a is PropertyInfo && b is MethodInfo) { return ((PropertyInfo) a).GetGetMethod() == b; } return false; }to:
private static bool MembersMatch(MemberInfo a, MemberInfo b) { if (a == b) { return true; } if ((a.DeclaringType.IsAssignableFrom(b.DeclaringType) || b.DeclaringType.IsAssignableFrom(a.DeclaringType)) && a.Name == b.Name) { return true; } if (a is MethodInfo && b is PropertyInfo) { return a == ((PropertyInfo) b).GetGetMethod(); } if (a is PropertyInfo && b is MethodInfo) { return ((PropertyInfo) a).GetGetMethod() == b; } return false; }If some one approve this, then add to new versions of SubSonic... Or, if I'm someday examine Git, then I'm could do it with myself.
I get an overflow error message when create a new post .I am from the UK so my datetime settings might be causing this but I dont think the app should cause an error.
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
This relates to 3.0.0.1
Comments
johnsheehan
Sun Jul 12 21:37:14 -0700 2009
| link
You need to post some more details and sample code otherwise we can't determine the problem. I would also suggest that unless you believe it to be a SubSonic bug, you should post it on StackOverflow.com (with more details and sample code).
Well, this is the SimpleRepository example untouched (apart from adding RunMigrations in the controller). Create new post from the interface and I get that error when you save the post. I kind of think its a bug in the code that doesnt handle international date formats as I have not changed anything in the example.
ActiveRecord.tt line 296 wrap property name with [] e.g.
Public ReadOnly Property [<#=propName #>] As IQueryable(Of <#=fk.OtherClass #>)ActiveRecord.tt line 322 wrap property name with [] e.g.
Public Property [<#=col.CleanName #>] As <#=col.SysType #><#=CheckNullable(col)#>ActiveRecord.tt line 76 needs Implements iActiveRecord.SetIsNew
Public Sub SetIsNew(isNew As Boolean) Implements IActiveRecord.SetIsNewStructs.tt line 45 wrap property name with [] e.g.
Public ReadOnly Property [<#=col.CleanName#>] As IColumn
Comments
In adventureworks and northwind, lots of fields like "Name" that are protected, need to have [Name] instead of Name.
Hi Rick- I don't know VB and this template set is a contribution. I'd love your help here...
And I'd love to help. Can I send you the changes and have you post them to git hub?
Closing this waiting for push. Also please put template issues in the Template project :). Thanks for your help!
Not that it really matters but I had also noticed this issue and solved it in a slightly different manner. I may be anal, but I didn't like the idea of escaping all properties with square brackets so I created a function to only add square brackets where the resulting name would conflict with known VB.net keywords (see http://github.com/BlackMael/SubSonic-3.0-Templates/commit/06b47692eae0b2f99bedab7a1c6e2e9f6fabb3d7 )
ActiveRecord.tt and numeric ModifiedBy / CreatedBy fields
3 comments Created 5 months ago by kmckelvinMy pre-existing DMS database has integer fields for ModifiedBy & CreatedBy, which relate back to user ids inside my database.
It appears the ActiveRecord.tt generates the Update and Add methods with the code
if(String.IsNullOrEmpty(this.ModifiedBy)) this.ModifiedBy=Environment.UserName;Problem is that this.ModifiedBy is of type Int32 (mapped correctly from my database, but gives invalid argument on String.IsNullOrEmpty) and also the assignment to Environment.UserName is thus erroneous.
It also has created methods taking string arguments for username:
public void Add(string username){ this.CreatedBy=username; Add(); }and
public void Update(string username, IDataProvider provider){ this.ModifiedBy=username; Update(provider); }Hope this has enough info for you guys :)
Best RegardsComments
Our convention is that these are strings with a name. If you want to change your templates to a different convention you can do that :)
Closing...
I may be rambling here, but I've found that by modifying the lambda expressions used in ActiveRecord.tt, that established conventions can be held, while catering for the case where we aren't working with strings.
I've tested this pretty thoroughly now on MSSQL, in both cases where i'm using int and varchar & nvarchar fields to hold my modifiedby / createdby user
This is what I did:
ActiveRecord.ttLine 398
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 415
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 436
<#if(tbl.Columns.Any(x=>x.Name=="CreatedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 443
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 456
<#if(tbl.Columns.Any(x=>x.Name=="CreatedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 486
<#if(tbl.Columns.Any(x=>(x.Name=="CreatedBy" || x.Name=="ModifiedBy") && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 491
<#if(tbl.Columns.Any(x=>x.Name=="CreatedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>Line 497
<#if(tbl.Columns.Any(x=>x.Name=="ModifiedBy" && (x.DbType == DbType.String || x.DbType == DbType.AnsiString))){#>I sincerely hope this helps your project. I'm very new to it, but it's making a HUGE impact on my overall development progress!
System.Double generates incorrect Create SQL for float
1 comment Created 5 months ago by billnetSimpleRepository, SQL2005.
A property of type Double gets translated to float(10,2), which is not valid. This should be just float, or float(53) (I guess?).For a quick fix, I changed line 146 in Sql2005Schema.cs from:
if(column.DataType == DbType.Double || column.DataType == DbType.Decimal)to just:
if (column.DataType == DbType.Decimal)
Comments
Database names that aren't a valid identifier don't generate correctly
2 comments Created 5 months ago by kamsarI have a database whose name contains hyphens. Whether this is good practice or not is beside the point, but when I generate subsonic ActiveRecord off of it, it will not compile as it uses the hyphens to create the code namespace, which is of course not valid.
I've got a patch for it that I put together that basically adds a simple method to strip nonalphanumeric characters from the database name before it's put into the namespaces and class names.
I will try to submit this patch once I figure out git a bit more :)
Comments
Git's not working out very well for me.
In any case the patch consists of this added to the Settings.ttinclude:
string CleanDatabaseName(string rawName)
{ return Regex.Replace(rawName, "[^A-Za-z0-9]", "_"); }and a bunch of places in ActiveRecord.tt and Context.tt where <#=DatabaseName#> turns into <#=CleanDatabaseName(DatabaseName)#>
There might be a better way to do it but that's quick n dirty.
If records is loading using GetPaged() method of IRepository interface or using other methods to load record, property IsNew is still set to true, while must be set to false. In fact property IsNew must be set to false in method SetKeyValue(), but this is not doing (this is problem of template) and SetKeyValue() method is never called, however on my opinion method SetKeyValue() must been called while any loading of record is processed.
Comments
SimpleRepository Example causing an error if RunMigrations is added
3 comments Created 5 months ago by coolcoderIf you install Subsonic 3.0.0.2 (or 3/3.0.0.1) and just edit the Home Controller to:
_repo = new SimpleRepository("Blog",SimpleRepositoryOptions.RunMigrations);
It will error with a truncate message even though no changes have been made to the Models. Is this due to the db that is supplied with the example not being built originally from the Model ?
I am using VSTS 2008 (Database Edition).
Comments
Hello. What's happening is that the example database have the body field as a long string type, but the Post class does not have the SubSonicLongString attribute set to the Body property, what makes that with the RunMigrations enabled the Migrate() tries to convert the long string type to a shorter, but it already have some big example string there, so it would be truncated. You can workaround this by adding [SubSonic.SqlGeneration.Schema.SubSonicLongString] right before the Body property in the Post class.
Hope it helps.Thank you, I thought it had something to do with the db not being created by the example project in the first instance. Perhaps the example project should be updated - surprised I am the only person to try this.
Subsonic 3 Linq Projection from joined query fails results in null values
3 comments Created 5 months ago by jonhiltWhen using LINQ to execute a joined query across several ActiveRecord classes, projecting the results into a different class appears to result in several of the projected class's fields being null.
More information can be found on Stack Overflow here
http://stackoverflow.com/questions/1105052/subsonic-3-linq-projection-issue
Comments
I can't repro this and I think you might have some reserved word conflicts in there. Here is a test I just ran that passes:
[Fact] public void Joined_Projection_Should_Return_All_Values() { var qry = (from c in _db.Customers join order in _db.Orders on c.CustomerID equals order.CustomerID join details in _db.OrderDetails on order.OrderID equals details.OrderID join products in _db.Products on details.ProductID equals products.ProductID select new CustomerSummaryView { CustomerID = c.CustomerID, OrderID = order.OrderID, ProductName = products.ProductName }); Assert.True(qry.Count() > 0); foreach (var view in qry) { Assert.False(String.IsNullOrEmpty(view.ProductName)); Assert.True(view.OrderID > 0); Assert.False(String.IsNullOrEmpty(view.CustomerID)); } }Thanks.
It's strange, I've just made some changes to my original query to see if I can get this working and still get null customer types (now called categories).
[Fact]
public void Joined_Projection_Should_Return_All_Values() { var db = new DemoDB(); var customers = (from c in db.tblCustomers join address in db.tblAddresses on c.Address equals address.AddressId join category in db.tblCustomerCategories on c.CustomerCategory equals category.CustomerCategoryId select new CustomerSummaryView { CustomerName = c.CustomerName, CustomerCategory = category.CategoryDescription, Postcode = address.Postcode }); Assert.True(customers.Count() > 0); foreach (var view in customers) { Console.WriteLine(view.CustomerName); Console.WriteLine(view.CustomerCategory); Console.WriteLine(view.Postcode); Assert.NotNull(view.CustomerName); Assert.NotNull(view.CustomerCategory); Assert.NotNull(view.Postcode); } }When I use join query like in this one:
var result = from p in db.bih_Companys join t in db.bih_CompanyCategories on p.CompanyID equals t.CompanyID where t.CategoryId == id orderby p.CompanyID select p;I get an error: Column "dbo.bih_Companys.CompanyID" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
When I remove ORDER BY from my query I get an error :The ranking function "ROW_NUMBER" must have an ORDER BY clause
because it is missing an ORDER BY.
The problem is in result.ToPagedList() function When it counts the total records. In that query ORDER BY should not be there.
in my case this is SQLquery that counts total records : SELECT COUNT(*) FROM [dbo].[bih_Companys] AS t0 INNER JOIN [dbo].[bih_CompanyCompanies] AS t1 ON ([t0].[CompanyID] = [t1].[CompanyId]) WHERE ([t1].[CategoryId] = 2) ORDER BY [t0].[FirmaID]
But when I remove order by from original query then the subsonic query has this error:
"SELECT [t0].[AdminId], [t0].[Address], [t0].[Activ], [t0].[Email], [t0].[Fax], [t0].[CompanyID], [t0].[CompanyName], [t0].[CountyId], [t0].[Description], [t0].[PartnerStatus], [t0].[Priority], [t0].[Phone], [t0].[UserId], [t0].[Web] FROM ( SELECT [t1].[AdminId], [t1].[Address], [t1].[Activ], [t1].[Email], [t1].[Fax], [t1].[CompanyID], [t1].[CompanyName], [t1].[CountyId], [t1].[Description], [t1].[PartnerStatus], [t1].[Priority], --here is an error row number function is missing order by ROW_NUMBER() OVER() AS rownum,
[t1].[Phone], [t1].[UserId], [t1].[Web] FROM [dbo].[bih_Companys] AS t1 INNER JOIN [dbo].[bih_CompanyCategories] AS t2 ON ([t1].[CompanyID] = [t2].[CompanyId]) WHERE ([t2].[CategorieId] = 2) ) AS t0 WHERE [t0].[rownum] BETWEEN (5 + 1) AND (5 + 5)"Please Help
Comments
This is an issue we know about - thanks for reporting :)
Thanks for reply.
I have one more question.
Is this possible to solve?
Because I stuck here!
Or is there some other way to make join query's make work with paged results!We are implementing Subsonic 3 instead Subsonic 2 because 3 simplifies paging allot more then Subsonic 2.
Please answer!Thanks in advance!
Yes you can use the old query syntax and use "ToPagedList()" on the reader
http://subsonicproject.com/docs/Simple_Query_Tool
I fixed this today - will push tonight. You can get latest source if you like.
Hey Rob what version is the fix found in. I am still seeing this error in 3.0.0.3
Stored Procedure method parameters not in same order as defined in DB
2 comments Created 5 months ago by johnsheehanMinor issue, but broke some existing code I'm migrating from 2.2 to 3.0. The parameters for the generated SP proxies aren't in the same order as they're defined in the DB. I have limited evidence of this, but it appears they're being generated in alphabetical order.
Comments
SubSonic.Schema.DatabaseTable.Name conflicts
4 comments Created 5 months ago by lukesampsonI get the compiler warning "'[ActiveRecord generated ClassName].Name' hides inherited member 'SubSonic.Schema.DatabaseTable.Name'. Use the new keyword if hiding was intended." compiler warning when the ActiveRecord templates generate code for my DB, because my table has a column called "Name".
Would it be possible to rename DatabaseTable.Name > DatabaseTable.TableName or something similar that is less likely to conflict?
Comments
You're asking me to rename a core class so you don't get naming conflicts in your DB? Ummm - no :p
... and that came across a little too snarky :). Sorry bout that. You can re-engineer the templates as you need to. Naming, as always, is a major issue for us and it's why I made the T4 templates. So you can rename things as needed.
lukesampson
Thu Jul 09 22:17:55 -0700 2009
| link
Haha! That's ok - I guess it was a pretty annoying request :)
I'm not sure I understand - are you suggesting I modify ActiveRecord.tt and Structs.tt to watch out for database columns named "Name" and name the corresponding code properties something else? Or do you mean I should hand-edit the generated code and name the property something else, every time the T4 tool runs? Or something else?
How about if DatabaseTable implements the IDBObject.Name property explicitly instead of implicitly? Then when Structs.tt generates a table class for a table with a column named "Name" there won't be a conflict.
Feel free to tell me to get lost now!
LOL - well I guess I would probably start by saying "don't worry about the warning" but if you have FxCop going and it's messing up some reports (or something) then you could tweak the templates to get around it. It might be a tad involved - but basically it would be changing how Structs.tt does the schema thing and how Context.tt calls it.
ActiveRecord - IsLoaded not set true when query is executed
5 comments Created 5 months ago by awbackerExecuting a linq query casues the IsNew flag to get True, but the IsLoaded flag to be False.
I am not sure what that the isLoaded flag is intended to mean, but I take it that it refers to the object being loaded from the db. The generated class's Load() method doesn't get called, it all happens in subsonic.extensions.database.ToEnumerable<t> (which creates the type, then calls database.Load<t>), which never sets the _isLoaded flag.
Since <t> is IActiveRecord, should it be calling instance.Load(reader, false)?
Comments
Perhaps this should actually be a call to item.SetIsLoaded(true) inside the database.Load<t>() call?
spookytooth
Thu Jul 09 13:09:14 -0700 2009
| link
I don't follow you - I need to repro this.
hehe :) it goes like this for me...
var list = (from p in data.products.all() where p.createdOn > now select p).ToList()
stack:
Extensions.Database.Load /t/ Extensions.Database.ToEnumerable /t/ .... Linq.Structure.DbQueryProvider.Execute Linq.Structure.Query... .... System.Linq.ToEnumerable()The object is created in Database.ToEnumerable(), calling the default constructor which sets IsNew=true. The Database.Load() function then populates the object /t/. The only places in the object that set IsLoaded are the Load(reader,...) functions and SetIsLoaded(). Since the object didn't load itself (database.load did), and SetIsLoaded did not get called, the object is not marked that way. It also means that IsNew does not get reset to false.
I noticed this because it causes the IsDirty property to fail, since that reliese on dirtyColumns which is not populated by the setter since isLoaded is false.
ActiveRecord - Properties { set; } could use updated handler
2 comments Created 5 months ago by awbackerThe current handler calls onchanged, even though the value may not have changed. A simple change to something like this would prevent that. This will come in handy when INotifiyPropertyChange is implemented as well (either privately or publicly)
if (_Amount != value) { _Amount = value; var col = tbl.Columns.SingleOrDefault(x => x.Name == "Amount"); if (_isLoaded && col != null && !_dirtyColumns.Contains(col)) _dirtyColumns.Add(col); OnChanged(); }Comments
Could be related to issue #3. Using LINQ templates and latest source.
See screenshot of code and generated SQL: http://screencast.com/t/EI77UERiT68
Comments
Error executing sprocs (parameter SqlDbType is set to variant)
2 comments Created 5 months ago by johnsheehanI have a sproc with three int params. When I try to call it, I get this:
Implicit conversion from data type sql_variant to int is not allowed. Use the CONVERT function to run this query.
Debugging the cmd object being called in DbDataProvider line 133 I see that all three params are DbType = object and SqlDbType is Variant.
It looks like QueryCommand.AddParameter(name, value) always sets the DbType to 'object' which then gets improperly translated to the SQL needed.
Database is SQL 2005
I'm trying to fix it, but if anyone else knows the fix, I'd be happy to save the time :)
Comments
johnsheehan
Wed Jul 08 22:53:04 -0700 2009
| link
If I update the generated StoredProcedures.cs file to use the overload that lets you specify DbType, it works. Is the QueryCommand.AddParamter overload without this supposed to try to determine the type before adding the parameter?
------ Short Description ------
I am getting the following error message in Context.cs:
The type or namespace name 'CustomerTable' could not be found (are you missing a using directive or an assembly reference?)I get one of these errors for each of the tables in my database.
------ Long Version ------
- Using ActiveRecord
- My database has one table: Customer with two fields: CustomerID and CustomerName
- In the generated Context.cs, in the "void Init()" method, in the ' Schemas ' region
The compiler is unable to find 'CustomerTable'
#region ' Schemas ' if(DataProvider.Schema.Tables.Count == 0) { DataProvider.Schema.Tables.Add(new CustomerTable(DataProvider)); } #endregion
Comments
Make sure you regenerate your Structs.tt class - it defines this stuff.
BatteryMan
Wed Jul 08 22:44:51 -0700 2009
| link
Thanks. It might be worth updating the ActiveRecord demo video to include the Structs.tt file (or place a comment somewhere on the page where the video is hosted).
Guid as primary key is empty on insert with SimpleRepository
3 comments Created 5 months ago by esp0Using this class:
public class Task { public Guid ID { get; set; } public string Description { get; set; } }The ID field is always 00000000-0000-0000-0000-000000000000 unless i explicitly set it to something else. Shouldn't it be NEWID() instead?
I see that this problem was avoided in the example by using a constructor (see c943d2b), but should this be required?
Comments
Yes - we can't default to knowing what you need :). You'll need to set the Guid in code (which is how it's usually done) or you can set the props in the DB as you need.
In thinking this over - I don't see a problem defaulting the SQL column to newID. I'll add this for SQL Server.
Renaming a column with SimpleRepository deletes content
3 comments Created 5 months ago by esp0From http://blog.wekeroad.com/subsonic/subsonic-30-the-simplerepository/ :
Yes – if you change your model then your DB will be synchronized. No, you will not lose dataBut if I rename a column, the data is lost. How can we solve this? With some kind of [OldColumn("ColumnWithTypo")] on the property?
Comments
Renaming a column doesn't delete the data - it runs an ALTER statement which is not a DROP statement. Can you give me something to repro this please.
Here is code to repro, hope this comment fields supports markdown:
Using SQL Server 2005 express on an ASP.NET app:
public class Task { public int ID { get; set; } public string Description { get; set; } } protected void Page_Load(object sender, EventArgs e) { var repo = new SimpleRepository("myDB", SimpleRepositoryOptions.RunMigrations); var task = new Task(); task.Description = "This is now: " + DateTime.Now.ToString(); repo.Add(task); Response.Write(task.Description); }After running the page_load 4 times, this is the table data:
select * from tasks: ID Description ----------- -------------------------------- 111 This is now: 09.07.2009 08:06:16 112 This is now: 09.07.2009 08:06:17 113 This is now: 09.07.2009 08:06:17 114 This is now: 09.07.2009 08:06:18 (4 row(s) affected)Now, after right-clicking on the Description-property, choosing refactor and then rename, i get this class:
public class Task { public int ID { get; set; } public string TaskDescription { get; set; } }And then running the page-load gives me this data, notice that the description is gone for the old data:
select * from tasks: ID TaskDescription ----------- -------------------------------- 111 112 113 114 115 This is now: 09.07.2009 08:08:04 (5 row(s) affected)This produces the folowing SQL wich clearly is dropping the column (with the data)
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF_Tasks_Description]') AND type = 'D') ALTER TABLE Tasks DROP CONSTRAINT [DF_Tasks_Description] ALTER TABLE [Tasks] DROP COLUMN Description; ALTER TABLE [Tasks] ADD TaskDescription nvarchar(255) NOT NULL CONSTRAINT DF_Tasks_TaskDescription DEFAULT ('') UPDATE Tasks SET TaskDescription=''
2 comments Created 5 months ago by esp0Error message when defining custom primary key with SimpleRepositoryFixedxThe Folowing code generates an error from sql on an asp.net web site (sql express 2005) with an empty database:
public class Task { [SubSonicPrimaryKey] public int myPK { get; set; } [SubSonicLongString] public string Description { get; set; } }code-behind:
protected void Page_Load(object sender, EventArgs e) { var task = new Task(); task.Description = "This"; var repo = new SimpleRepository("myDB", SimpleRepositoryOptions.RunMigrations); repo.Add(task); }Errormessage:
Cannot insert explicit value for identity column in table 'Tasks' when IDENTITY_INSERT is set to OFF.I am using the latest binary from 3.0.0.1
Comments
1 comment Created 5 months ago by georgexcollinsError on create post in SimpleRepo Example siteFixedxCreating a new post in the simple repo example site throws the following error:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
Line 138: scope.Dispose();
Line 139: //rethrow retaining stack trace.
Line 140: throw;
Line 141: }in \SubSonic.Core\DataProviders\DbDataProvider.cs Line: 140
In debugger the values for the PostedOn dateTime seem reasonable so I'm not sure what the problem is.
Comments
If you call Update or Save when using the Active Record test mode you get an error.
System.NotImplementedException: The method or operation is not implemented. at SubSonic.Repository.TestRepository`1.Add(T item, IDataProvider provider) at Model.Generated.Product.Add(IDataProvider provider) in ActiveRecord.cs: line 708 at Model.Generated.Product.Save(IDataProvider provider) in ActiveRecord.cs: line 721 at Model.Generated.Product.Save() in ActiveRecord.cs: line 715
See this question at Stack Overflow for more detail...
http://stackoverflow.com/questions/1091041/subsonic-3-active-record-testing
Comments
6 comments Created 5 months ago by nathanbAcceptedxnull varchar PK after ActiveRecord saveFixedxI'm working with the trunk as of 9:45PM CST. I'm using ActiveRecord templates against Sql 2008. My table has a varchar PK that is set externally. The insert works fine, but SCOPE_IDENTITY returns nothing and SubSonicRepository.Add() (line 204) sets my PK property to nothing. (not null). When I ToString the result, it shows up as an empty string, which isn't caught by the null check. Later, this value is re-enforced to the entity in the ActiveRecord template where it SetKeyValue(the empty result).
My hack fix for this is to compare the ToString() value to string.Empty and in the ActiveRecord template, check to see if it's numeric... (total hack for a quick fix).
What are your thoughts?
Comments
It will be null no matter what so it's almost impossible to fix this issue. I reviewed your changes and SetKeyValue() already checks for null - so there's no choice as far as the stock templates are concerned.
You could create a partial for this class and override "OnSaved", then ping the DB for a reload - that would solve this problem.
I see now. SetKeyValue also accommodates DBNull which is the value my PK is getting set to. The source of the problem now seems to be caused by the extra (if SqlClient) property set in SubSonicRepository.Add. After the executescalar, it resets the primary key then returns the result. Since SetKeyValue works the way it should does this seem redundant? Is it for one of the other template types?
I tested OnSaved(). In this case, by the time it fires, the PK has already been lost.
You know another quick fix for this would be to just add a DBNull check on Line 204 in SubSonicRepository.Add(). Then it wouldn't be too invasive.
This is already happening isn't it? Also - the PK "never was" so it can't be lost - it's in the DB so you'll need to pull it manually. Closing this (reopen if you think it needs to be)
OK fixed up - just added a quick check to Add():
var newKey=_repo.Add(this,provider); if(newKey!=KeyValue()) this.SetKeyValue(newKey);
1 comment Created 5 months ago by bilfActive Record generates strings for int 32 columns + mysql.FixedxHi,
My int 32 id columns are being generated as strings, so the following doesnt compile unless I wrap my ID in quotes:
var item = _webproject.SingleOrDefault(x => x.unique_ID == "16450000");However, when debugging, this throws an error:
"Object of type 'System.UInt32' cannot be converted to type 'System.String'." in public static _webproject SingleOrDefault
single=results.ToList()[0];Ta'
Bob
Comments
HI,
I'm having a play with the SS3 linq features, but have the following error when trying to view the results from a simple query. (Either by adding a breakpoint or a watch)The code is:
var result = db._hotkeylayouts.Where(x => x.system_number == 4832934969383991);
The code executes fine, however when I try to view the result via Watch, I get the error "Function evaluation timed out".
This is using mysql on vista x64
Bob
Comments
DbDataProvider.ExecuteReader doesn't allow allow access to the command object.
6 comments Created 5 months ago by markkemper1Comments
markkemper1
Tue Jul 07 00:55:55 -0700 2009
| link
Currently when executing the ExecuteReader method there is no way to get the output parameters.
To get the output parameters first you need to read all the results and call reader.Close()So there needs to be a way to get the actual parameters used on the command object to retrieve output values.
markkemper1
Tue Jul 07 01:10:10 -0700 2009
| link
For the moment I have hacked this by..
1) adding a new method to the DbDataProvider
public DbDataReader ExecuteReader(QueryCommand qry, out DbCommand command)
2) Adding a property to the StoredProcedure class
public DbCommand DbCommand { get; private set; }
3) Modify the ExecuteReader of the storedProcedure class to
DbCommand cmd;
var result = Provider.ExecuteReader(Command, out cmd);
this.DbCommand = cmd;
return result;So now , I can do the following and get my TotalRecords output parameter...
using (IDataReader reader = procedure.ExecuteReader()) { results = ExtractList<T>(reader, map, ExtractItem<T>); reader.Close(); } procedure.Command.GetOutputParameters(procedure.DbCommand);
markkemper1
Tue Jul 07 19:16:47 -0700 2009
| link
Hi Rob, I have tried (first time using git).
I actually modified the QueryCommand object to keep the reference to the actual dbCommand.I also noted that there appears to be 2 places where a DbCommand is created from a QueryCommand.
There is the: AddParams(cmd,qry) inside DbDataProvider
and : ToDbCommand(trannie) inside QueryCommand.
gufranshaikh84
Sun Jul 26 01:33:48 -0700 2009
| link
Can you please update this in the source code, because I am not getting it to work.
Regards
Gufran Sheikh
gufranshaikh84
Mon Jul 27 12:34:17 -0700 2009
| link
Is this issue really closed ? because I can't see the code mentioned above and not getting the OUTPUT parameter using ExecuteReader.
Rob, Please let me how to get OUTPUT parameter if this issue has already been fixed.
No SQL Server Server Compact Edition templates
3 comments Created 5 months ago by jswagerThere doesn't appear to be any templates for Windows SQL Server Compact Edition (SQL Server CE) yet. I don't know if anyone else is working on them, but I'm working with some template code to see if I can submit something back to the project.
Comments
I wouldn't get too excited yet. I'm having some problems with the sdf file location; keeps wanting to add App_Data to the path. Tables and columns including primary keys seem to be generating, although not tested. Foreign keys are giving me problems - the SQL to get the list of foreign key constraints uses an embedded SELECT, which SQLCE doesn't support. So I'm going to have to some unwrapping and multiple SQL calls I suspect to get the actual foreign keys out. Or I could just skip them for now; I'm not sure how a foreign key affects the generated code (being very much a SubSonic novice).
SimpleRepository - Lambda Parameter not in scope
1 comment Created 5 months ago by adiomarin
1 comment Created 5 months ago by adiomarinSQLite Migrations - Pk Autoincrement is never appliedFixedxIsNew is not working correctly in ActiveRecord Templates
1 comment Created 5 months ago by jcoenenIsNew() is still true after a Save or a load from the database. Causing subsequent calls to Save() to add new records instead of updating the existing record.
Below is a unit test to recreate the issue
Index: ActiveRecord.cs
--- ActiveRecord.cs (revision 527) +++ ActiveRecord.cs (working copy) @@ -18,5 +18,13 @@
Assert.NotNull(table); }[Fact]public void IsNew_Should_Be_False_After_Save(){var category = new Southwind.Category();category.CategoryName = "Test";category.Save();Assert.False(category.IsNew());
+}[Fact]public void IsNew_Should_Be_False_Load_From_DB(){var category = new Southwind.Category.SingleOrDefault(c => c.CategoryID== "1");Assert.False(category.IsNew());
} }}
Comments
`SimpleRepository.All<T>()` doesn't run migrations
1 comment Created 5 months ago by troethomWhen making a call to
SimpleRepository.All<T>()it doesn't run automatic migration. I would expect this behaviour, because it is counterintuitive to require to add data before being able to perform a list operation.Another solution would be to make
SimpleRepository.Migrate<T>()public, which again would seem a bit off, as it makes the simple repository more complex.I have sent a pull request for a solution to this issue.
Comments
Hi,
OtherColumn and ThisColumn are set to the raw version of the column name. They should use a CleanUp version of the column name.
ActiveRecord.tt, line 313 :
where items.<#=fk.OtherColumn#> == _<#=fk.ThisColumn#>Can generate bad code if the column had a space in his name.
Comments
SQLServer.ttinclude: Line 62 : GetSPParams(string spName) :
always returns an empty list if you use SQL Express.
The database name seems to be really really long like "249823749822\downloads\blah\BLOG.MDF" however the actual variable just has "blog" .. Setting it to null i.e string[] restrictions = new string[4] { null, null, spName, null }; resolves the issue. However this seems to be a fundamental issue with express..Comments
I got this Error when i am trying to configure the project:
Error 3 .. System.ArgumentException: Keyword not admitted: 'userid'.
in System.Data.Common.DbConnectionOptions.ParseInternal.....etcthe connection string is:
server=localhost; userid=root;password=sa;pooling=yes;Database=NorthwindMySqli got another error when i use trusted connection and set persist security =true;
thanks
Comments
Not sure why you'd use trusted connection - this MySQL right?
Ok, userid works fine using mysqlconnector simply but anyway i changed the keyword to user id and right! the error vanished... but now :( some issue...i see that inside the folder called ActiveRecord there are a file SQLServer.ttinclude but i am using MySql so how can i get it works? i've tried to do it but cant get it works..sorry!
I've tried to change to this new release, i am using mysql 5.0 and i did all it says in docs to setting up my project but...Not lucky! :( ...the project doesnt compile because an error with MySQL.ttinclude ..
the project wont generate it dicatates....help or something
thanks
Comments
ChangeTypeTo<T>() extension method returns object
4 comments Created 5 months ago by johnsheehanIt would be nice to have this cast to and return T since it's specified in the method signature.
Comments
johnsheehan
Sun Jul 05 13:09:11 -0700 2009
| link
I would like to change this:
private static T Get<T>(string key) { return (T)ConfigurationManager.AppSettings[key].ChangeTypeTo<T>(); }To this by moving the (T) cast into ChangeTypeTo():
private static T Get<T>(string key) { return ConfigurationManager.AppSettings[key].ChangeTypeTo<T>(); }
johnsheehan
Sun Jul 05 13:10:55 -0700 2009
| link
Nevermind, I thought the old Utility.ChangeType() did this, but it doesn't. So no big deal.
2 comments Created 5 months ago by johnsheehanGenerated stored procedure methods do not take nullable objectsAcceptedxThis is a simple change in Settings.ttinclude to include the ? after the parameter type, but I thought it should be included in the default template.
Comments
.Add() doesn't set primary key property to returned value from insert
9 comments Created 5 months ago by johnsheehanThis may be by design but it's different than 2.x. Inserting does not update the PK column with the new ID generated. I know .Add() returns the new value but it would nice to not have to manually assign it.
Comments
Can you be more specific? The SimpleRepo does just this - what scenario are you talking about?
johnsheehan
Sun Jul 05 13:06:38 -0700 2009
| link
var db = new DatabaseNameDB(); var repo = new SubSonicRepository<Tag>(db); Tag tag = new Tag(); tag.Label = "SubSonic"; tag.UserId = 1; var result = repo.Add(tag); // result = new ID // tag.TagId = 0
johnsheehan
Sun Jul 05 15:37:33 -0700 2009
| link
Yes
Aha! OK thanks I get it :). I'll try to deal with this in the coming few days but if you get a chance to fork/push - that would rock. I'll put you on commit (been meaning to).
johnsheehan
Sun Jul 05 20:28:13 -0700 2009
| link
I added a patch for this. Didn't find a unit test for SubSonicRepository so it is currently untested.
johnsheehan
Sun Jul 05 20:28:34 -0700 2009
| link
I did test it working with a SQL 2008 DB though.
Is this also related to varchar PK? I'm getting the same thing in ActiveRecord templates. But my manually set PK isn't returned after save because it uses SCOPE_IDENTITY. Repo.Add() returns null and resets my entity id.
johnsheehan
Wed Jul 08 09:05:23 -0700 2009
| link
This issue isn't related to that. I would create a new one (if you haven't already) and make sure to specify the problem is with ActiveRecord. There just needs to be a check put in place to make sure the PK column is a SCOPE_IDENTITY compatible type before being set.
2 comments Created 5 months ago by johnsheehan!= null doesn't generate correct SQLLinq ParserxComments
3 comments Created 5 months ago by johnsheehan3.0 Download has out-of-date Classes.tt fileT4 TemplatesxIt's missing the changes checked in in r529 on Google code (it still calls .GetRepo which doesn't exist)
Comments
johnsheehan
Sun Jul 05 05:31:23 -0700 2009
| link
Very strange. I just redownloaded it and the templates are up to date. The original download file I have called SubSonic_3_Final.zip has outdated templates.
This feature is coming soon. Sit tight!












Fixed and pushed to master