- Home
- LLBLGen Pro
- Bugs & Issues
.Net SqlClient Provider Inserting Error with UDT
Joined: 26-May-2009
Hello, I am getting this Error trying to save an Entity with an UDT Column.
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException was caught Message="An exception was caught during the execution of an action query: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 6 (\"@Path\"): Data type 0xE7 has an invalid data length or metadata length.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception." Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20" RuntimeBuild="09032009" RuntimeVersion="2.6.0.0" QueryExecuted="\r\n\tQuery: INSERT INTO [cvrdb-dev].[rdb].[Comp2Roles] ([Comp_id], [Role], [Seq], [Path]) VALUES (@Compid, @Role, @Seq, @Path)\r\n\tParameter: @Compid : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 12.\r\n\tParameter: @Role : AnsiString. Length: 40. Precision: 0. Scale: 0. Direction: Input. Value: \"HDD.Data\".\r\n\tParameter: @Seq : Int16. Length: 0. Precision: 5. Scale: 0. Direction: Input. Value: 0.\r\n\tParameter: @Path : String. Length: 8000. Precision: 0. Scale: 0. Direction: Input. Value: \"/2/0/\".\r\n" StackTrace: at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.BatchActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteActionQuery(IActionQuery queryToExecute, ITransaction containingTransaction) at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.AddNew(IEntityFields fields, ITransaction containingTransaction) at cvrdbMainORM.EntityClasses.Comp2RolesEntityBase.InsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.CallInsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, ITransaction transactionToUse, Int32& totalAmountSaved) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(IPredicate updateRestriction, Boolean recurse) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(Boolean recurse) at CVRDBWeb.CompRightDetails.GV_SubComp_RowUpdating(Object sender, GridViewUpdateEventArgs e) in D:\VisualStudio\CVRDBWebInit\cvrdbTemplates\Templates\CompRightDetails.ascx.cs:line 359 InnerException: System.Data.SqlClient.SqlException Message="The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 6 (\"@Path\"): Data type 0xE7 has an invalid data length or metadata length." Source=".Net SqlClient Data Provider" ErrorCode=-2146232060 Class=16 LineNumber=1 Number=8016 Procedure="" Server="erlh1hxa" State=30 StackTrace: 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.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() InnerException:
Evironment:
SQL Server 9.0.3310 (9.0 SP2) .Net 3.5 SP1 System.Data: v. 2.0.50727 Visual Studio 2008
LLBLGen Pro Ver. 2.6 Final (Aug 26th, 2009) (I downloaded the latest Release, refreshed my project, regenerated, readded all refereneces and rebuilt.)
Lines producing the error:
Comp2RolesEntity c2rUpdating;
if (RoleOld != null)
{ // Existing RoleSeq edited
// Get the edited instance of Comp2Role
c2rUpdating = new Comp2RolesEntity(ComponentObject.Id, RoleOld, SeqOld);
}
else
{ // New RoleSeq defined
// Create a new instance of Comp2Role
c2rUpdating = new Comp2RolesEntity();
c2rUpdating.Compid = ComponentObject.Id;
c2rUpdating.Path = ctr.Path;
}
if (RoleNew != null)
{ // New Role & Seq were defined
// Get an instance of the desired Role & Seq
RoleSeqEntity roleseqnew = new RoleSeqEntity(RoleNew, SeqNew);
try
{
// Save the instance if new
if (roleseqnew.IsNew)
{
roleseqnew.Save(true);
}
// Set the new RoleSeq & Save the Comp2Role (Role Definition)
c2rUpdating.RoleSeq = roleseqnew;
// Do I need this?
// Stragely w/o these 2 lines LLBLGen was trying to insert the Entity with only Compid & Path as VALUES
// Produced the same error, but I can't see it succeeding anyway, as these 2 are both PKs & FKs
c2rUpdating.Role = roleseqnew.Role;
c2rUpdating.Seq = roleseqnew.Seq;
c2rUpdating.Save(true);
}
catch (Exception ex)
{
throw new Exception("Saving RoleSeq threw Exception", ex);
}
}
The UDT is properly read by the code. Here is the declaration of the class:
[CLSCompliant(true)]
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(
Format.UserDefined,
IsByteOrdered = true,
IsFixedLength = false,
MaxByteSize = 8000)]
public class CompPath : INullable, IBinarySerialize
...
public CompPath(string value)....
A Constructor for String exists as you can see...
Please help! I can't imagine what is going wrong... Thank you!
Please post the DDL of your UDT table.
Side note: I recommend you upgrade to the latest SQL Server 2005 build (SP3): 9.00.4230
(EDIT) DbType.String is always in Unicode format, so its maximum allowed size is 4000 characters (8000 bytes). If you specify size 8000, this would mean 8000 characters, which would be 16,000 bytes. So for Varchar you can have up to 8000 chars but in Nvarchar you can only have 4000
Joined: 26-May-2009
Hi, to your request:
CREATE TABLE [rdb].[Comp2Roles](
[Comp_id] [int] NOT NULL,
[Role] [varchar](40) NOT NULL,
[Seq] [dbo].[PathEdge] NOT NULL,
[Path] [dbo].[CompPath] NOT NULL,
CONSTRAINT [PK_Comp2Roles] PRIMARY KEY CLUSTERED
([Comp_id] ASC, [Role] ASC, [Seq] ASC)
ALTER TABLE [rdb].[Comp2Roles] WITH CHECK ADD CONSTRAINT [FK_Comp_C2Rol] FOREIGN KEY([Comp_id])
REFERENCES [rdb].[Component] ([id]) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE [rdb].[Comp2Roles] WITH CHECK ADD CONSTRAINT [FK_RS_C2Rol] FOREIGN KEY([Role], [Seq])
REFERENCES [rdb].[RoleSeq] ([Role], [Seq]) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE [rdb].[Comp2Roles] ADD CONSTRAINT [DEF_Comp2Roles_Seq] DEFAULT ((0)) FOR [Seq]
The 2 Types are declares as follows:
CREATE TYPE [dbo].[PathEdge] FROM [smallint] NULL
CREATE TYPE [dbo].[CompPath]
EXTERNAL NAME [cvrdbSql].[CompPath]
The UDT CompPath has actually a List<Int16> as underlying storage structure. So, I guess you are suggesting that I change MaxByteSize to 4000? I don't expect to be storing even nearly as large objects. Or should I provide a constructor for SqlString or SqlChars or sth. like that? And still... my type is stored in binary. There should be no problem for it being declared as 8000 Bytes long. The DAL on the other hand is sending a VALUE in String format. This is not something I can control. The DAL should actually consider that and set the Length to 4000 in the Parameter, or not?
Parameter: @Path : String. Length: 8000. Precision: 0. Scale: 0. Direction: Input. Value: \"/2/0/\"
should be...
Parameter: @Path : String. Length: 4000. Precision: 0. Scale: 0. Direction: Input. Value: \"/2/0/\"
Anyways, I will change the MaxByteSize to 4000 and see if it helps. Or should I actually do just the opposite and change it to 16000? I am lost here. Here is what MSDN has to say on the topic:
You must specify the MaxByteSize property with the UserDefined serialization Format.
MaxByteSize must be between 1 and 8000.
For a UDT with user-defined serialization specified, MaxByteSize refers to the total size of the UDT in its serialized form as defined by the user. Consider a UDT with a property of a string of 10 characters (Char). When the UDT is serialized using a BinaryWriter, the total size of the serialized string is 22 bytes: 2 bytes per Unicode UTF-16 character, multiplied by the maximum number of characters, plus 2 control bytes of overhead incurred from serializing a binary stream. So, when determining the value of MaxByteSize, the total size of the serialized UDT must be considered: the size of the data serialized in binary form plus the overhead incurred by serialization.
To me this is a DAL issue. The question is just: Is it your code or is it SqlClient? I will try the workaround with 4000 MaxByteSize anyways...
Side note: I recommend you upgrade to the latest SQL Server 2005 build (SP3): 9.00.4230
Unfortunately not an option. I have no control over the SQL Server and the IIS. Company policy: everything has to be validated first. We are still using IE 6!!!
Thanks for your tip, but please see further into that. Cheers, Vasil
Joined: 26-May-2009
Hi, an update... Changed MaxByteSize of the UDT from 8000 to 4000 and now it works! Still after some thought I really think you should recheck the code. It's only a guess but I think the Parameters for the SQL query are being prepared by your code. And obviously the DbType Length of the UDT is taken into consideration. But if the VALUE is supplied as String, which seems to be the case for UDTs, you should make sure that the Length of the Parameter is <=4000. The MaxByteSize of UDTs concerns only their binary serialized representation. It does not necessarily say anything about the Length of their String representation. Don't we all love them...
Anyways, here is the new Exception I am getting. The good news is it shows the difference to before. (And actually it succeeds if I set the RoleSeqEntity to something already existing in the DB). But it does not succeed if the related RoleSeqEntity is also new. So basically what follows is on the side and not connected to the previous issue. Here is the error.
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException was caught Message="An exception was caught during the execution of an action query: The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_RS_C2Rol\". The conflict occurred in database \"cvrdb-dev\", table \"rdb.RoleSeq\".\r\nThe statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception." Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20" RuntimeBuild="09032009" RuntimeVersion="2.6.0.0" QueryExecuted="\r\n\tQuery: INSERT INTO [cvrdb-dev].[rdb].[Comp2Roles] ([Comp_id], [Role], [Seq], [Path]) VALUES (@Compid, @Role, @Seq, @Path)\r\n\tParameter: @Compid : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 12.\r\n\tParameter: @Role : AnsiString. Length: 40. Precision: 0. Scale: 0. Direction: Input. Value: \"HDD.Data\".\r\n\tParameter: @Seq : Int16. Length: 0. Precision: 5. Scale: 0. Direction: Input. Value: 0.\r\n\tParameter: @Path : String. Length: 4000. Precision: 0. Scale: 0. Direction: Input. Value: \"/2/0/\".\r\n" StackTrace: at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.BatchActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteActionQuery(IActionQuery queryToExecute, ITransaction containingTransaction) at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.AddNew(IEntityFields fields, ITransaction containingTransaction) at cvrdbMainORM.EntityClasses.Comp2RolesEntityBase.InsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.CallInsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, ITransaction transactionToUse, Int32& totalAmountSaved) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(IPredicate updateRestriction, Boolean recurse) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(Boolean recurse) at CVRDBWeb.CompRightDetails.GV_SubComp_RowUpdating(Object sender, GridViewUpdateEventArgs e) in D:\VisualStudio\CVRDBWebInit\cvrdbTemplates\Templates\CompRightDetails.ascx.cs:line 363 InnerException: System.Data.SqlClient.SqlException Message="The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_RS_C2Rol\". The conflict occurred in database \"cvrdb-dev\", table \"rdb.RoleSeq\".\r\nThe statement has been terminated." Source=".Net SqlClient Data Provider" ErrorCode=-2146232060 Class=16 LineNumber=1 Number=547 Procedure="" Server="erlh1hxa" State=0 StackTrace: 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.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() InnerException:
And here is the code again causing that:
// Get an instance of the desired Role & Seq
RoleSeqEntity roleseqnew = new RoleSeqEntity(RoleNew, SeqNew);
try
{
// Save the instance if new
if (roleseqnew.IsNew)
{
roleseqnew.Save(true);
}
// Set the new RoleSeq & Save the Comp2Role (Role Definition)
c2rUpdating.RoleSeq = roleseqnew;
// Do I need this?
// Strangely w/o these 2 lines LLBLGen was trying to insert the Entity with only Compid & Path as VALUES
// Produced the same error, but I can't see it succeeding anyway, as these 2 are both PKs & FKs
c2rUpdating.Role = roleseqnew.Role;
c2rUpdating.Seq = roleseqnew.Seq;
c2rUpdating.Save(true);
}
....
To give you the big picture:
TABLE Role (Role, Description) PK(Role) TABLE RoleSeq (Role, Seq) PK(Role, Seq) FK(Role => Role.Role) TABLE Comp2Roles (Comp_id, Role, Seq, Path) PK (Comp_id, Role, Seq) FK (Comp_id => Component.id) FK (Role => RoleSeq.Role, Seq => RoleSeq.Seq)
So the strange thing is that the statement
roleseqnew.Save(true);
doesn't seem to have any effect. Nothing is saved in the DB. And depending on if I comment or uncomment the 2 lines in the code (after // Do I need this?) I am just getting a different Exception. Lines are commented:
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException was caught Message="An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'Role', table 'cvrdb-dev.rdb.Comp2Roles'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception." Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20" RuntimeBuild="09032009" RuntimeVersion="2.6.0.0" QueryExecuted="\r\n\tQuery: INSERT INTO [cvrdb-dev].[rdb].[Comp2Roles] ([Comp_id], [Path]) VALUES (@Compid, @Path)\r\n\tParameter: @Compid : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 12.\r\n\tParameter: @Path : String. Length: 4000. Precision: 0. Scale: 0. Direction: Input. Value: \"/2/1/\".\r\n" StackTrace: at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.BatchActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteActionQuery(IActionQuery queryToExecute, ITransaction containingTransaction) at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.AddNew(IEntityFields fields, ITransaction containingTransaction) at cvrdbMainORM.EntityClasses.Comp2RolesEntityBase.InsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.CallInsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, ITransaction transactionToUse, Int32& totalAmountSaved) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(IPredicate updateRestriction, Boolean recurse) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(Boolean recurse) at CVRDBWeb.CompRightDetails.GV_SubComp_RowUpdating(Object sender, GridViewUpdateEventArgs e) in D:\VisualStudio\CVRDBWebInit\cvrdbTemplates\Templates\CompRightDetails.ascx.cs:line 363 InnerException: System.Data.SqlClient.SqlException Message="Cannot insert the value NULL into column 'Role', table 'cvrdb-dev.rdb.Comp2Roles'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated." Source=".Net SqlClient Data Provider" ErrorCode=-2146232060 Class=16 LineNumber=1 Number=515 Procedure="" Server="erlh1hxa" State=2 StackTrace: 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.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() InnerException:
Am I doing something wrong? You will probably tell me to RTFM and I will! Again! But as far as I understood calling Save(true) saves the Entity and all related Entities recursively. And besides I am saving the new RoleSeqEntity myself and it still does not propagate
Please help me! This is getting so frustrating...
Thank you! Greetings,
Vasil
We should examine this first:
if (roleseqnew.IsNew)
{
roleseqnew.Save(true);
}
What is the generated sql of this? That is, in addition to the exception information. In other words, RoleSeq is saved and if yes, What is its generated sql?
Does RoleSeq have any identity (auto-increment) column?
Joined: 26-May-2009
Good Morning,
I am pasting you the DDL for the 2 Tables that play a role here:
CREATE TYPE [dbo].[PathEdge] FROM [smallint] NULL
CREATE TABLE [rdb].[Role](
[Role] [varchar](40) NOT NULL,
[Description] [dbo].[NotesType] NULL,
CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED ([Role] ASC)
)
CREATE TABLE [rdb].[RoleSeq](
[Role] [varchar](40) NOT NULL,
[Seq] [dbo].[PathEdge] NOT NULL,
CONSTRAINT [PK_RoleSeq] PRIMARY KEY CLUSTERED ([Role] ASC, [Seq] ASC)
)
ALTER TABLE [rdb].[RoleSeq] WITH CHECK ADD CONSTRAINT [FK_Role_RS] FOREIGN KEY([Role])
REFERENCES [rdb].[Role] ([Role]) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE [rdb].[RoleSeq] ADD CONSTRAINT [DEF_RoleSeq_Seq] DEFAULT ((0)) FOR [Seq]
The only thing that is perhaps a little extraordinary here is that the COLLATION of Role is Latin1_General_CI_AI, while the default DB COLLATION is Latin1_General_BIN2.
I made a clean Generate of SelfServicing (in an empty Folder) and made a small test Page to isolate the problem. It only tries to save a new RoleSeqEntity. Still no success. Here is the code:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
String role; //= "HDD.Data";
Int16 seq = 0;
bool isnew, isdirty, result;
role = TB_role.Text;
if (TB_seq.Text != String.Empty)
seq = Convert.ToInt16(TB_seq.Text);
if (role != null && role != String.Empty)
{
RoleSeqEntity rse = new RoleSeqEntity(role, seq);
rse.AfterSave += new EventHandler(rse_AfterSave);
isnew = rse.IsNew; //true
isdirty = rse.IsDirty; //false
result = rse.Save(); //true
// tried rse.Save(false) : no difference
// if the Role I try to insert is already defined in the Role Tbl or not
//doesn't make a difference either
isnew = rse.IsNew; //true
isdirty = rse.IsDirty; //false
rse.Refetch();
isnew = rse.IsNew; //true
isdirty = rse.IsDirty; //false
}
}
}
void rse_AfterSave(object sender, EventArgs e)
{
throw new Exception("Saved!"); //never executed
}
The values of the variables I read when debugging are written as comments. I don't debug your libraries though. I haven't had the time to figure out how... And I don't know how to get the SQL that the Save() statement is generating. No Exception is thrown in this code. It just doesn't save anything in the DB. If you tell me how to get to the generated SQL I will. I guess... till later!
RoleSeqEntity rse = new RoleSeqEntity(role, seq); result = rse.Save(); //true
The above code won't save. As you can see IsDirty is false. There is nothing to save as the PK fields are not set. PK values passed in the CTor are only used to fetch the entity.
The following code will save:
RoleSeqEntity rse = new RoleSeqEntity();
rsa.Role = role;
rsa.Seq = seq;
result = rse.Save();
Joined: 26-May-2009
It did! Thanks! And still, I have to say I am rather perplexed by this behavior. I assumed that the framework will save (insert) the Entity when IsNew == true regardless of IsDirty. Do you have a reason for not doing that? It would have been very convenient. Calling the CTor with the PKs returns an instance if already present and a new instance with the PKs already set otherwise. A subsequent Save() if it had the behavior I assumed, would make sure an Entity with the desired properties exists in the storage and the user is holding an instance of it... Anyways, I can live with it as it is. I only wanted to give you some feedback on my experience. Thanks again for the help and keep on the good work!
Cheers, Vasil
And still, I have to say I am rather perplexed by this behavior. I assumed that the framework will save (insert) the Entity when IsNew == true regardless of IsDirty. Do you have a reason for not doing that? It would have been very convenient.
Yes as there is not changed fieldsand the entity is not dirty so there is nothing to save. Same as you do:
var customer = new CustomerEntity();
customer.Save();
Passing PK values in the CTor doen't set the PK field, since most of the time the PK fields are readOnly as in the case of Identity Columns. So CTor parameters are only used for fetching/filtering.
And the Fields' properties are left to do the job of checking either the field can be set and hence Set is allowed, or not (readOnly field).