I have an application with a dataset linked to an sql server database. I have updated some of the names or foreign keys and primary keys in the sql server. How do I make those changes translate to the data set. For example, I had a primary key called fk_temsempl_xxxxx. I changed it to fk_temsempl on the sql database. How do I get that change to show in the dataset designer in visual studio?
I have tried running custom tool by right clicking on the dataset and clicking run custom tool. That didnt work. I tried configuring the table adapter of one of the tables where a change occured, but the name of the relation didnt change.
You actually just right click the relation and choose Edit Relation... or double click on the line (when the mouse cursor changes from arrow to drag symbol) but I honestly wouldn't bother; you'll then have further refactoring to do in the code anywhere the relation is used, and it can be heavily used by visual designers.
You also get the problem that VS may not help you with the refactoring: in data binding scenarios most things that can be a source of data can also be a collection of multiple things that can be a valid DataSource. They then rely on a string DataMember to determine which of the collections of data in the data source should be used for the data.
For example, when a bindingsource is bound to list a DataTable, the bindingsource.DataSource property might be the DataSet object that contains the DataTable, and thebindingsource.DataMemberis a string of "YOUR_TABLE_NAME". the BindingSource might not be bound asmyBindignSource.DataSource = myDataSet.MyDataTable`. Refactoring inside strings involves a find and replace
DataRelations in a DataSet are created from foreign keys as they were discovered when the relevant table(s) were added to the dataset but it is important to note that, like DataTables and everything else, they are NOTHING to do with the database schema objects at all - they aren't permanently associated with them, the dataset entities are just set up looking something like the database objects when they (dataset entities) are first created. DataTables are created from only those columns selected, and whatever .NET datatypes closely resemble the types output by the query. For a table of:
Person
------
Name VARCHAR(50)
SSN INTEGER
Birthdate DATE
If you created the table with SELECT * FROM Person you'd get a datatable with Name (string), SSN (int), Birthdate (datetime) but if you made a new datatable in the dataset based on SELECT LEFT(Name, 1) as Initial, PADLEFT(SSN, 20) as PadSSN, DATEDIFF(day, Birthdate, NOW()) as AgeDays FROM Person then you'd get a datatable of Initial (string), PadSSN (string), AgeDays (int) - i.e. the datatable looks nothing like the db table. This concept of disconnection between dataset and db is pervasive, and really the only things that relate in any way to the database are the properties that specify which DB table/column a particular DataTable/DataColumn relates to for purposes of loading/saving data. Your Person.Name datacolumn can be renamed to Blahblah, but it will still have a .SourceColumn property that is set to "Name" - that's how the mapping between dataset and db works; dataset is predominantly completely independent of the db. Renaming a DB column would require a change to the SourceColumn property only
DataRelations don't even have this notion of linking to the parent relation in the database; there's no SourceRelation or SourceFK proeprty because there is no need to. They're set up with the same rules and a generated name all based on the rules of the FK, but then they function independently and only within the dataset. If you rename or even remove an FK from the db the dataset will carry on working in the same restricted way it always did; adding a datarow to a child table when no aprent row exists for it will throw an exception - none of it anything to do with the FK in the db, and the DataRelation can have different rules to the FK (e.g it can cascade deletes when the FK is NOACTION) or even different columns. You can have more or fewer DataRelations than the DB has FKs
Run Custom Tool is not a "contact the DB and see what changes have occurred there and replicate them into the dataset", it is a "turn the XSD that describes the dataset into a bunch of C# classes that implement strongly typed dataset/table/relation/column etc objects". Any time you change the XSD by making an edit in the visual designer and hit save, the custom tool is run. If you edit the XSD directly in a text editor you may need to run it manually to have your changes reflected in c# classes
Reconfiguring a tableadapter probably won't do anything to the relations either; its solely concerned with changing the datatable and tableadapter. If you really want to refresh the relations, delete the datatable from the set and recreate it. Be prepared for a potentially significant mop up/refactoring of code
Related
I have an ASP.NET Core application that uses EF6 for dealing with a third-party application's database.
Everything is working as expected, but I'm unable to insert rows into a joining table.
I have two tables, Users and Groups, and a joining table GroupUser that identifies which users are members of which groups. Users has a PK of UserId, and Groups has a PK of GroupId.
GroupUser has only 3 columns: GroupId, UserId and another column (which is irrelevant for this post). The two foreign keys in this table identify a unique record.
Every time I try to insert into GroupUser, I get the inner exception
The table/view does not have a primary key defined. The entity is read-only
The error is correct. There is no PK, but both of the FKs are marked as keys in the model. Shouldn't VS be able to use those as a PK somehow?
The inserts used to work as some point, but required some manual modification of the .edmx file as XML in order to work. Unfortunately, our version control records containing this modification have been lost (and I wasn't the one originally working on this).
I've looked at and tried about a dozen articles around this, but they generally have to do with views instead of tables, so don't seem applicable to my case. The ones that did seem applicable didn't solve the issue.
The only other clue I have for a solution is this comment I found in the code:
// Important note: If you have updated the edmx file in the [redacted]
// project and suddenly start having problems, the edmx file may need to be
// edited as an xml file so that you can make changes necessary to make
// VS believe that the GroupUser table has a primary key. See revision #[redacted]
I'm able to insert into User and Group tables just fine, and as I've said, I don't have access to the revision log mentioned.
Edit: The database is for a third-party application, and unfortunately, it's not as simple as just modifying the table to add a PK. I wish it was. Problem would be solved. But I've been advised by the vendor not to make this change, as it may have unexpected consequences, and would void our support.
How can I 'trick' EF into thinking the table has a key? I'm also open to other workarounds. Modifying the DB structure is currently out of the question.
I'm using the Dynamics connector in Azure Data Factory.
TLDR
Does this connector support loading child records which need a parent record key passed in? For example if I want to create a contact and attach it to a parent account, I upsert a record with a null contactid, a valid parentcustomerid GUID and set parentcustomeridtype to 1 (or 2) but I get an error.
Long Story
I'm successfully connecting to Dynamics 365 and extracting data (for example, the lead table) into a SQL Server table
To test that I can transfer data the other way, I am simply loading the data back from the lead table into the lead entity in Dynamics.
I'm getting this error:
Failure happened on 'Sink' side. ErrorCode=DynamicsMissingTargetForMultiTargetLookupField,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=,Source=,''Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=Cannot find the target column for multi-target lookup field: 'ownerid'.
As a test I removed ownerid from the list of source columns it loads OK.
This is obviously a foreign key value.
It raises two questions for me:
Specifically with regards to the error message: If I knew which lookup it needed to use, how can I specify which lookup table it should validate against? There's no settings in the ADF connector to allow me to do this.
This is obviously a foreign key value. If I only had the name (or business key) for this row, how can I easily lookup the foreign key value?
How is this normally done through other API's, i.e. the web API?
Is there an XRMToolbox addin that would help clarify?
I've also read some posts that imply that you can send pre-connected data in an XML document so perhaps that would help also.
EDIT 1
I realised that the lead.ownertypeid field in my source dataset is NULL (that's what was exported). It's also NULL if I browse it in various Xrmtoolbox tools. I tried hard coding it to systemuser (which is what it actually is in the owner table against the actual owner record) but I still get the same error.
I also notice there's a record with the same PK value in systemuser table
So the same record is in two tables, but how do I tell the dynamics connector which one to use? and why does it even care?
EDIT 2
I was getting a similar message for msauto_testdrive for customerid.
I excluded all records with customerid=null, and got the same error.
EDIT 2
This link appears to indicate that I need to set customeridtype to 1 (Account) or 2 (Contact). I did so, but still got the same error.
Also I believe I have the same issue as this guy.
Maybe the ADF connector suffers from the same problem.
At the time of writing, #Arun Vinoth was 100% correct. However shortly afterwards there was a documentation update (in response to a GitHub I raised) that explained how to do it.
I'll document how I did it here.
To populate a contact with against a parent account, you need the parent accounts GUID. Then you prepare a dataset like this:
SELECT
-- a NULL contactid means this is a new record
CAST(NULL as uniqueidentifier) as contactid,
-- the GUID of the parent account
CAST('A7070AE2-D7A6-EA11-A812-000D3A79983B' as uniqueidentifier) parentcustomerid,
-- customer id is an account
'account' [parentcustomerid#EntityReference],
'Joe' as firstname,
'Bloggs' lastname,
Now you can apply the normal automapping approach in ADF.
Now you can select from this dataset and load into contact. You can apply the usual automapping approach, this is: create datasets without schemas. Perform a copy activity without mapping columns
This is the ADF limitation with respect to CDS polymorphic lookups like Customer and Owner. Upvote this ADF idea
Workaround is to use two temporary source lookup fields (owner team and user in case of owner, account and contact in case of customer) and with parallel branch in a MS Flow to solve this issue. Read more, also you can download the Flow sample to use.
First, create two temporary lookup fields on the entity that you wish to import Customer lookup data into it, to both the Account and Contact entities respectively
Within your ADF pipeline flow, you will then need to map the GUID values for your Account and Contact fields to the respective lookup fields created above. The simplest way of doing this is to have two separate columns within your source dataset – one containing Account GUID’s to map and the other, Contact.
Then, finally, you can put together a Microsoft Flow that then performs the appropriate mapping from the temporary fields to the Customer lookup field. First, define the trigger point for when your affected Entity record is created (in this case, Contact) and add on some parallel branches to check for values in either of these two temporary lookup fields
Then, if either of these conditions is hit, set up an Update record task to perform a single field update, as indicated below if the ADF Account Lookup field has data within it
I have problems to refresh the structure of a table in my universe.
We have added some data to a reference table which is used in universe. After checking the new data in (Oracle 11g) database, found everything OK.
Then opened up designer in BO, imported the universe, looked up the associated table which only shows the existing items (not the new ones) - which seemed ok for me. I clicked on "View"/"Regenerate structure" but BO says that the structure does not need to be regenerated?
I have no idea what goes wrong and how I can add the new items to the table in my universe. Or do I have to update the content of a table differently?
It's possible that Designer isn't properly reading the database's data dictionary, and therefore not seeing the new column.
Data fields do not have to be present in the model in Designer in order for objects to reference them. So I would create a new universe object that references one of the new fields, and parse it. If it parses, then the field really is there and Designer just isn't seeing it. However if it doesn't work (i.e., you get an "invalid identifier"-type error), then the field is not there.
Joe's answer gave me the hint to check again why the new fields have not been there. And finally I found it. My "table" was a view which had to be actualized (SQL-select statement) and after that I could pick up the data into my universe and as shown in reports. Now everything is fine.
Ok, so I have 2 entities: Course and Industry
The industry entity is just a reference table which lists all available Industries that can be tagged to a course, to categorizing them. I put in a many to zero or one relationship (a course can choose to have an industry or not, while an industry can be tagged with many courses).
I know I've played around with the diagrams a bit, adding and removing associations in the past.
Now here is the odd part: The column mappings for Course has 2 similar columns, IndustryId and Industry_Id
I suspect it's from a past association, but thought EF would have taken care of that.
Here is the problem:
In my view that creates the course, the IndustryId is the property which needs to be populated. When I create new courses, I see the IndustryId in the database populated.
However, when I access Industry's properties through Course (Course.Industry.Description) nothing is populated. It can't seem to get the Industry entity.
I see the IndustryId populated in the db, so I tried to populate the Industry_Id column. That fixed it.
Weird enough, the property declared in the model is IndustryId, so that column is populated in the db. But when I try to get Industry entities through Course, it needs the Industry_Id, which I don't quite know where it is from.
Anyone have any ideas?
It sounds like in your updating from the database, you changed the column name on your tables from Industry_Id to IndustryId. The next time you updated from the database, EF5 (which can't determine that this is the same column, as it matches on names) dropped the mapping for Industry_Id, and added a new column called IndustryId.
However, you had already created the foreign-key mapping in your EDMX file based on the Industry_Id column - which is why you get the issue around needing it when loading related records.
In general, when using Database-First, whenever you rename a column in the database, you need to update your EF5 model and update / correct any such discrepancies.
I created 3 tables in SQL Designer -
Community { ID, Name, Description }
Audience { ID, Type, Value}
Community_Audience { CommunityID, AudienceID }
I imported this schema into the EDMX designer in Visual Studio 2010, right-clicked in the designer and selected "Generate Database from Model" to script out the schema. When I looked at the generated script, it is scripting it out like this -
Community { ID, Name, Description } -- Column names not sorted alphabetically.
Audience { ID, Type, Value} -- Column names not sorted alphabetically.
Community_Audience { AudienceID, CommunityID } -- Column names sorted alphabetically. CommunityID is after AudienceID.
This is causing my data seeding scripts to fail as I'm not specifying the column names -
INSERT INTO Community_Audience { 'guid', 'guid' }
I understand I can update my data seeding scripts to include column names or re-arrange the underlying xml in the edmx file but I don't want to go that route as I'll be clearing out the entities (tables) in the edmx and importing fresh schema from the database too often. I was wondering if there is setting that will prevent the designer from sorting alphabetically. Strangely, it only happens to the cross ref tables (like Community_Audience) and not the primary ones (like Community and Audience in this case).
Thanks for any help.
You have described both your choices - either modify your INSERT statements which should not be so hard and you will have to do it only once or try to modify EDMX (bad way if you use refreshing model from database). Entity designer really doesn't have a feature to define ordering in columns. Generating the database script is driven by separate component. It is based on Windows Workflow Foundation 4 and it can be replaced with your custom workflow but it is a lot of work without any real reason. The solution is modifying INSERT statements.
What I don't understand is why do you use Generate Database from Model in the same time as well as refreshing model from database.