How to add Triggers to Transitions in Enterprise Architect using C# - c#

Moving on from my previous problem, now I need to add Triggers to my transitions in State Machine diagram. How to acheive this using C#. The following creates a transition and its gaurd value but the trigger is not getting added.
EA.Connector trans = psosDiagramElement.Connectors.AddNew(tb1[i].Text, "StateFlow");
trans.ClientID = GetElementByName(txtSourceElement.Text);
trans.MetaType = "Transition";
trans.TransitionGuard = tb1[i].Text;
trans.SupplierID = GetElementByName(cmb1[i].SelectedItem.ToString());
trans.Direction = "Source -> Destination";
trans.Constraints.AddNew("A", "Signal");
trans.Update();

I don't think that there is a direct API call available to update the trigger.
TransitionEvent property of connetor will only update specification value.
Workaround for updating trigger is to hit a direct query using below call.
Repsitory.Execute(TriggerQuery)
You need to update\add a value in t_xref with
name as MOFProps
Type as connector property
Behaviour as trigger and
Description column you need to update the GUID value of triggers ( it will also accept Comma separated value as shown in diagram below )
Sample Insert query: Insert into t_xref (Name,Type,Visibility,Behavior,Description,Client) values ('MOFProps','connector property','public','trigger','triggereaguid1,triggereaguid2','connectorid');

Related

How best to achieve automatic integer row version incrementation?

So I have a model with an int Version property. I need it to be int and I need it to auto-increment each time I save, and I need it to throw if there is a concurrency error.
It cannot be a byte array nor a DateTime.
I have tried with .IsRowVersion(), but it doesn't seem to work on int. At least, it does absolutely nothing when used with (localdb)\\mssqllocaldb.
How can I best achieve automatic row version incrementation using EF Core + MSSQL? Perhaps I need to create some SQL triggers manually upon initialization?
Was able to solve this by marking the Version property with:
.HasDefaultValue(0).IsRowVersion()
And running the following SQL statement upon initialization:
var tableName = Model.FindEntityType(typeof(MyEntity)).GetTableName();
var sql =
$#"CREATE TRIGGER [dbo].Update{tableName}
ON [dbo].[{tableName}]
FOR UPDATE
AS
UPDATE [{tableName}]
SET Version = [{tableName}].Version + 1
FROM [{tableName}]
INNER JOIN INSERTED i ON [{tableName}].Id = i.Id";
await Database.ExecuteSqlRawAsync(sql);

Saving table/column updates c# entity

I am trying to find a neater way to save table/column updates. I have an object representing the current order table entry and an object with all updated values. I want to compare each variable with matching names in each object and save the update to the database if different.
The current way I am doing this (which I know is badly written) is as follows:
if (currentOrder.Comment != editedOrder.Comment)
{
createOrderUpdateRecord("Comment", currentOrder.Comment.ToString(), editedOrder.Comment.ToString(), OrderID);
currentOrder.Comment = editedOrder.Comment ;
anyChangesMade = true;
}
if (currentOrder.CustomerName != editedOrder.CustomerName )
{
createOrderUpdateRecord("CustomerName ", currentOrder.CustomerName .ToString(), editedOrder.CustomerName .ToString(), OrderID);
currentOrder.CustomerName = editedOrder.CustomerName ;
anyChangesMade = true;
}
and then in the createOrderUpdateRecord method, I save the information to an edits table.
In case anyones interested I ended up using the tracker enabled db context library alongside entity framework to track changes to table fields, which did the job perfectly
In case you are using the normal .NET Winforms DataGridView when you refer to table/column-updates:
There is an event called "CellValueChanged". Also there is "CellEndEdit". If you subscribe to either of those, you could set a "changed"-variable to true to track if you must update the value in the database.

SSIS: Column Size Not Changing Based on Query

I have a package. It has a query that feeds into a Script Component.
In the query I am selecting a varchar(8) column from a table and then I CAST(myDateCol AS varchar(10)).
SELECT
myPK,
CAST(myDateCol AS varchar(10)), --myDateCol defined as varchar(8)
myOtherCol
FROM
MyServer.MySchema.MyTable
In my script, I am trying to add two characters to the Row.myDateCol in Input0 but I get a Buffer Error and it is in the property setter for myDateCol. You can see that it sets the property to 8 characters but errors out after that.
What I've done is add an output column with Length = 10, set it, and mapped that to the next component in the package but that seems a little silly.
Is there a way to force the size of your input columns based off of the query OR is there a way that I can manually force a refresh in case the package is just stuck thinking that I'm dealing with a varchar(8) as the CAST operation was added later?
Additional Info:
Row.myDateCol = "20170404"
Row.myDateCol = "2017-04-04" // Errors out
This is normal behavior for SSIS. When you create a data source which uses a SQL query, SSIS will look at your query and build the the metadata for the dataflow. The data source will only recalculate that metadata if you change the structure of your query, for example number columns or their names.
The easiest way to force a refresh of the data types without resorting to renaming columns is to go to the columns page of the data source editor, Untick and then tick the top tick box of the Available External Columns. This will deselect all columns and re-select them and at the same time refresh the metadata. You can easily confirm this by hovering your mouse over the External\Output column names listed in the lower section.
Your problem is the result of dealing with Date(Time) as text instead of the number(s) it is. And I really cannot tell from your question if you want to want to add the extra characters added in at the Data Layer (Sql) or at the Application (C#) Layer.
Casting VarChar(8) => VarChar(10) will still just return VarChar(8) if you don't fill in (pad) that value. You could try a Cast VarChar(8) to Char(10).
Another option would be a double conversion of your column value to Date and then back to your desired varchar(10).
SELECT myPK,
Convert(VarChar(10), Convert(Date, myDateCol, 112), 120),
myOtherCol
FROM
MyServer.MySchema.MyTable
So, after some playing around, I found that renaming the column changed the size to varchar(10) per below:
SELECT
myPK,
CAST(myDateCol AS varchar(10)) AS DATECOL,
myOtherCol
FROM
MyServer.MySchema.MyTable
I then changed it back
SELECT
myPK,
CAST(myDateCol AS varchar(10)),
myOtherCol
FROM
MyServer.MySchema.MyTable
And the change stuck. I don't know why or how but VS/SSIS somehow never refreshed itself to change to a different type. I assume it has no handling for query changes after the initial query is input unless names/aliases change.
This wasn't just my machine either. Weird.

Sitecore 8 Update 5 FieldChanges functionality during publish

We are using Sitecore 8 update-5. We would like to check which values changed in a specific field during a publish. For this we are subscribed to the item:saved event handler. When extracting the ItemChanges parameter from the event arguments we use the FieldChanges property for that field. In the master database the FieldChanges dictionary contains only those fields that were changed and FieldChanges.OriginalValue and FieldChanges.Value contains the proper values (the old ones and the new ones). However when publishing from master to web DB it seems that the FieldChanges always contain all fields and the OriginalValue and Value properties are always the same. We tested this with items which were already existing in web database, using smart publish and a single language.
The question is this is how it should work or is this a bug?
Some example code:
var topicFieldID = new ID(RelatedTopic.FieldIDs.Topics); //getting the field ID
var changes = Event.ExtractParameter<ItemChanges>(args, 1); //in item:saved event handler
var oldIDs = changes.FieldChanges[topicFieldID]?.OriginalValue?.ToString().Split('|');
var newIDs = changes.FieldChanges[topicFieldID]?.Value?.ToString().Split('|');
and in our case the "oldIDs" and "newIDs" contain the same values in web DB
Regards,
Chris

How to get Indentity value back after insert

Given the following code (which is mostly irrelevant except for the last two lines), what would your method be to get the value of the identity field for the new record that was just created? Would you make a second call to the database to retrieve it based on the primary key of the object (which could be problematic if there's not one), or based on the last inserted record (which could be problematic with multithreaded apps) or is there maybe a more clever way to get the new value back at the same time you are making the insert?
Seems like there should be a way to get an Identity back based on the insert operation that was just made rather than having to query for it based on other means.
public void Insert(O obj)
{
var sqlCmd = new SqlCommand() { Connection = con.Conn };
var sqlParams = new SqlParameters(sqlCmd.Parameters, obj);
var props = obj.Properties.Where(o => !o.IsIdentity);
InsertQuery qry = new InsertQuery(this.TableAlias);
qry.FieldValuePairs = props.Select(o => new SqlValuePair(o.Alias, sqlParams.Add(o))).ToList();
sqlCmd.CommandText = qry.ToString();
sqlCmd.ExecuteNonQuery();
}
EDIT: While this question isn't a duplicate in the strictest manner, it's almost identical to this one which has some really good answers: Best way to get identity of inserted row?
It strongly depends on your database server. For example for Microsoft SQL Server you can get the value of the ##IDENTITY variable, that contains the last identity value assigned.
To prevent race conditions you must keep the insert query and the variable read inside a transaction.
Another solution could be to create a stored procedure for every type of insert you have to do and make it return the identity value and accept the insert arguments.
Otherwise, inside a transaction you can implement whatever ID assignment logic you want and be preserved from concurrency problems.
Afaik there is not finished way.
I solved by using client generated ids (guid) so that my method generated the id and returns it to the caller.
Perhaps you can analyse some SqlServer systables in order to see what has last changed. But you would get concurrency issues (What if someone else inserts a very similar record).
So I would recommend a strategy change and generate the id's on the clients
You can take a look at : this link.
I may add that to avoid the fact that multiple rows can exist, you can use "Transactions", make the Insert and the select methods in the same transaction.
Good luck.
The proper approach is to learn sql.
You can do a SQL command followed by a SELECT in one run, so you can go in and return the assigned identity.
See

Categories

Resources