update_recordset on tempDB table in ssrs report in d365 - report

I have to do an update for some fields after insert in a tempDB table inside a report.
I wrote this snippet:
private void updateField()
{
update_recordset GlobalTempDBVariable
setting field3 = GlobalTempDBVariable.field1 + GlobalTempDBVariable.field2;
}
But when i open the report i don't see this value updated. any helps?

Have you debugged the issue yet?
If you extend SrsReportDataProviderPreProcess in your DP class instead of SRSReportDataProviderBase you can debug your DP class and see if the table is even being filled up correctly.
If that doesn't clear anything up, try looping through the temp table at that point to see if there is even any data in there to update.

Related

Dynamics AX 2012 - Adding Tables to Database Logging Selection List

Is it possible to add tables to the Database Logging selection listing in AX 2012? If yes, is it possible to select which category each table appears in?
System Administration > Database > Database log setup > New
When I select Show all tables, some tables still do not appear. The tables do not appear in the Not specified category either.
We need to log additional AX built parameter tables as well developer built tables. The developer tables were built in the Development Workspace so we have access to all the Table properties.
You can add new button to the form with custom code
void clicked()
{
TableId promptTableId;
Dialog d;
DialogField df;
void createLine(DatabaseLogType logType)
{
DatabaseLog.logTable = promptTableId;
DatabaseLog.LogType = logType;
DatabaseLog.insert();
}
d = new Dialog("Enter table name");
df = d.addField(extendedTypeStr(TableName));
d.parmIsModal(true);
if (d.run())
{
promptTableId = tableName2id(df.value());
if (!promptTableId)
{
throw error(strFmt("Table %1 does not exists", df.value()));
}
ttsBegin;
createLine(DatabaseLogType::Insert);
createLine(DatabaseLogType::Update);
createLine(DatabaseLogType::Delete);
ttsCommit;
SysFlushDatabaseLogSetup::main();
info(strFmt("For table %1 (%2) records are created: %3, %4, %5."
, tableId2name(promptTableId)
, tableId2pname(promptTableId)
, DatabaseLogType::Insert
, DatabaseLogType::Update
, DatabaseLogType::Delete
));
}
super();
}
Method buildTableTree in form SysDatabaseLogWizard seems to be a good place to start looking for answers to your questions:
Is it possible to add tables to the Database Logging selection listing
in AX 2012?
Yes, it is possible.
If yes, is it possible to select which category each table appears in?
Yes, you have to modify the configuration key of the table to change the category. Please note that the root configuration key is used as category, so check first if the configuration key of the table has a parent key (e.g. table CommissionCustomerGroup has configuration key Commission which has configuration key LogisticsBasic as parent key, therefore the table appears in category Trade).
Please note that changing the configuration key can have additional consequences and I would not recommend to do it merely to change the category of the database logging selection.
Regarding your observation that some tables are not listed, there are several conditions that must be fulfilled so that a table gets listed:
must be enabled (dictTable.enabled(), I'm guessing that means the configuration key is enabled)
has table group main or option "Show all tables" is enabled or the table is already set up for logging
the table is neither table SysDataBaseLog nor SysUserLog
the table is not a temporary table
the table is not a map
a DictTable instance can be created for the table id
If your missing tables fulfill those conditions, I suggest debugging method buildTableTree of form SysDatabaseLogWizard to find out why a table is not added to the tree control.

Pre run SQL query to be used by ASP.net application

I have a SQL query which is running on a view and on top has lot of wild card operators, hence taking a lot of time to complete.
The data is consumed by an ASP.net application, is there any way I could pre-run the query once in a day so data is already there when asp.net application needs it and only pass on the parameter to fetch specific records.
Much simplified example would be
select * from table
Run every day and result stored somewhere and when asp.net passes on the parameter only specific records are fetched like
select * from table where field3 = 'something'
Either use SQLAgent (MSSQL) or equivalent to run a scheduled process that stores the result into a Table like this...
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MyTemporaryTable]') AND type in (N'U'))
BEGIN
TRUNCATE TABLE [dbo].[MyTemporaryTable];
INSERT INTO [dbo].[MyTemporaryTable]
SELECT * FROM [vwMyTemporaryTable];
END
ELSE
BEGIN
SELECT *
INTO [MyTemporaryTable]
FROM [vwMyTemporaryTableDataSource];
END
or you could store the result in ASP.Net as an Application/Session variable or even a Property in a class that is stored in Application/Session. The Property approach will load the data the first time it is requested, and use memory thereafter.
private MyObjectType _objMyStoredData;
public MyObjectType MyStoredData
{
get
{
if (_objMyStoredData == null)
{
_objMyStoredData = GetMyData();
}
return _objMyStoredData;
}
}
However, if your source data for this report is only 2,000 rows... I wonder if all this is really necessary. Perhaps increasing the efficiency of the query could solve the problem without delving into pre caching and the downsides that go with it, such as re-using data that could be out of date.
You can use redis. You can run the view once the user logs in. Then fill redis with the view data. Set that object in Session Context of user so that it is accessible on all pages. Then when the user logs out. clean up the redis. By this way user won't go to database everytime for result instead will get the data from redis cache. it's very fast. You can contact me if more help is needed.
you can mark it as answer if you find it helpful.

Entity Framework Code First Migrations: Set Primary Key Value

I have a table that stores some extra data for some rows of a table like:
public class QuoteExtra
{
[Key]
public int QuoteId { get; set; }
// More fields here
}
I'd like to be able to add rows to this table where I explicitly set the PK.
If I simply leave it as above, setting a value and submitting the row causes the value to be discarded and replaced with the auto-generated value from the database (and the column is defined as an Identity column in the actual schema).
This appears to be the right solution:
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
However this instead gets me the exception:
Cannot insert explicit value for identity column in table 'EnumTest' when IDENTITY_INSERT is set to OFF.
So, how do I write my class so that I'm able to set the value of a Primary Key in EF?
Edit:
I tried adding the following Code-based Migration to set IDENTITY_INSERT to ON:
public override void Up()
{
Sql("SET IDENTITY_INSERT QuoteExtra ON");
}
I ran it and tried again, but got the same exception as above. What's strange is the database does reflect this setting, and running SQL against it directly does allow me to insert arbitrary values in for the primary key - so it would appear Entity Framework itself is enforcing this rule, and neglecting to recognize that IDENTITY_INSERT is not in fact set to off. Do I need to set it somewhere in EF itself?
Edit 2:
I misunderstood IDENTITY_INSERT; I assumed setting it once left it on for that table indefinitely. In fact it lives as long as the "Session," meaning that for example setting it in a Migration means it lives... as long as that Migration runs, and has no bearing on future connections like my later .Add() with EF, which explains why I still got that exception - the DB really is the source of the exception, not EF. Since IDENTITY_INSERT is limited to at most one table per session it's a fairly inefficient way to do this - not creating an Identity PK column in the first place seems like a better route.
This is the proper way of creating a PK without Identity Autoincrement enabled:
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
However, if you add DatabaseGenerated(DatabaseGeneratedOption.None)] after EF Migrations has already created the table, it quietly does nothing to the table. If this is your scenario you need to add a manual migration to drop the table:
add-migration RecreateQuoteExtra
And in the migration:
public override void Up()
{
DropTable("QuoteExtra");
}
EF Automatic Migrations will then automatically recreate the table without the Identity constraint, which will then allow you to set the PK value anytime, without having to run any special commands like IDENTITY_INSERT ON.
It sounds like a less destructive way to do this is coming in EF7 ("Data Motion"), or you could write a lot of manual sql yourself in the migration to create temp tables and move data around if you wanted to avoid losing existing data in the table.
EDIT: Depending on your scenario EF Migrations might not recreate the table - if the class already exists and is already added to your DbContext it will just drop it and leave it at that, meaning your manual migration has to not only drop but also create the table. Not a big deal since the scaffolded code EF Migrations generates for you from add-migration will create these statements for you, but it is a bit more code to check over for issues.
It is right solution but only for a new table. If you change database generated option for an existing table, EF migrations are not able to perform this change and your QuoteId column is still marked as Identity in the database.
I could'nt solve this Problem with your Hints then i've tried to re-create the whole Database but it wasnt working, too.
To fix this you have to remove the identity: true property on the first(!) creation of the Column (e.g. Initial-Migration).
Maybe it will help someone..

asp.net InsertCommand to return latest insert ID

I'm unable to retrieve the latest inserted id from my SQL Server 2000 db using a typed dataset in asp.NET
I have created a tableadapter and I ticked the "Refresh datatable" and "Generate Insert, Update and Delete statements". This auto-generates the Fill and GetData methods, and the Insert, Update, Select and Delete statements.
I have tried every possible solution in this thread
http://forums.asp.net/t/990365.aspx
but I'm still unsuccesfull, it always returns 1(=number of affected rows).
I do not want to create a seperate insert method as the auto-generated insertCommand perfectly suits my needs.
As suggested in the thread above, I have tried to update the InsertCommand SQL syntax to add SELECT SCOPY_IDENTITY() or something similar, I have tried to add a parameter of type ReturnValue, but all I get is the number of affected rows.
Does anyone has a different take on this?
Thanks in advance!
Stijn
I decided to give up, I can't afford to waste any more time on this.
I use the Insert statement after which I do a select MAX(id) query to hget the insert ID
If anyone should have a solution, I'll be glad to read it here
Thanks
Stijn
I successfully found a way to get the incremental id after insert using my table adapter.
My approach is a little different, I'm using a Store procedure to make the insert, so my insert command has all the values but the ID, I made the sp return the ID just calling:
SET #ID=SCOPE_IDENTITY()
and then
COMMIT TRAN
and last line will be
RETURN #ID
Then I searched my table adapter parameters for InsertCommand and set the #RETURNVALUE to the column of the incremental ID of the table, so when it's executed automatically put the return value on the id field.
Hope this help
You need to tell your table's table-adapter to refresh the
data-table after update/insert operation.
This is how you can do that.
Open the properties of TableAdapter -> Default Select Query -> Advnaced options. and Check the option of Refresh the data table. Save the adapter now. Now when you call update on table-adapter, the data-table will be updated [refreshed] after the update/insert operation and will reflect the latest values from database table. if the primary-key or any coloumn is set to auto-increment, the data-table will have those latest value post recent update.
Now you can Call the update as TableAdapterObj.Update(ds.dataTable);
Read latest values from the DataTable(ds.dataTable) coloumns and assign respective values into the child table before update/insert. This will work exactly the way you want.
alt text http://ruchitsurati.net/files/tds1.png

LINQ: Cannot insert duplicate key row in object 'dbo.tblOutstandingCompletions' with unique index

I have an application (ASP.NET 3.5) that allows users to rerun a particular process if required. The process inserts records into an MS SQL table. I have the insert in a Try / Catch and ignore the catch if a record already exists (the error in the Title would be valid). This worked perfectly using ADO but after I conveted to LINQ I noticed an interesting thing. If on a re-run of the process there was already records in the table, any new records would be rejected with the same error even though there was no existing record.
The code is as follows:
Dim ins = New tblOutstandingCompletion
With ins
.ControlID = rec.ControlID
.PersonID = rec.peopleID
.RequiredDate = rec.NextDue
.RiskNumber = 0
.recordType = "PC"
.TreatmentID = 0
End With
Try
ldb.tblOutstandingCompletions.InsertOnSubmit(ins)
ldb.SubmitChanges()
Catch ex As Exception
' An attempt to load a duplicate record will fail
End Try
The DataContext for database was set during Page Load .
I resolved the problem by redefining the DataContext before each insert:
ldb = New CaRMSDataContext(sessionHandler.connection.ToString)
Dim ins = New tblOutstandingCompletion
While I have solved the problem I would like to know if anyone can explain it. Without the DataContext redefinition the application works perfectly if there are no duplicate records.
Regards
James
It sounds like the DataContext thinks the record was inserted the first time, so if you don't redefine the context, it rejects the second insert because it "knows" the record is already there. Redefining the context forces it to actually check the database to see if it's there, which it isn't. That's LINQ trying to save a round trip to the database. Creating a new context as you've done forces it to reset what it "knows" about the database.
I had seen a very similar issue in my code were the identity column wasn't an autoincrementing int column, but a GUID with a default value of newguid() - basically LINQ wasn't allowing the database to create the GUID, but inserting Guid.Empty instead, and the second (or later) attempts would (correctly) throw this error.
I ended up ensuring that I generated a new GUID myself during the insert. More details can be seen here: http://www.doodle.co.uk/Blogs/2007/09/18/playing-with-linq-in-winforms.aspx
This allowed me to insert multiple records with the same DataContext.
Also, have you tried calling InsertOnSubmit multiple times (once for each new record) but only calling SubmitChanges once?
gfrizzle seems to be right here...
My code fails with the duplicate key error even though I've just run a stored proc to truncate the table on the database. As far as the data context knows, the previous insertion of a record with the same key is in fact a duplicate key, and an exception is thrown.
The only way that I've found around this is:
db = null;
db = new NNetDataContext();
right after the SubmitChanges() call that executes the previous InsertOnSubmit requests. Seems kind of dumb, but it's the only way that works for me other than redesigning the code.

Resources