SAPUI5 Smart Table - Smart Field make field mandatory with annotation - annotations

Is it possible to make a Property in SAPUI5 Smart Table mandatory so that a user can't leave a field empty while editing it?
I have found this document saying that it should be possible to set mandatory field control on Property in metadata.xml file with annotation like this:
<Property Name="NameLast" Type="Edm.String" Nullable="false" MaxLength="40" sap:label="Last name" sap:field-control="7" />
But with this setting I am getting following error in console:
2017-04-14 11:37:36.691429 MockServer: Resource not found for the segment '7'
2017-04-14 11:37:36.707985 The following problem occurred: HTTP request failed404,Not Found,{"error":{"code":404,"message":{"lang":"en","value":"Resource not found for the segment '7'"}}} -
EDIT:
Later I found out that sap:field-control should not contain number, but a path expression to another property which contains the number. However this also doesn't work:
<Property Name="NameLast" Type="Edm.String" Nullable="false" MaxLength="40" sap:label="Last name" sap:field-control="Name_fc" />
<Property Name="Name_fc" Type="Edm.Byte" />
Value of Name_fc property is '7'. I don't see any console error now, however I can still leave the input (NameLast) field empty without any validation and send it to OData service, which is not what I expect.
Here is a link to an example from sap where they use required fields. I have no idea though how they made it.
https://sapui5.netweaver.ondemand.com/sdk/explored.html#/sample/sap.ui.comp.sample.smartfield/code/SmartField.view.xml

For OData v2 the sap:field-control annotation on the Property can be
used to specify whether the field is mandatory.
<Property Name="Customer" ... sap:field-control="mandatory"/>
<Property Name="CompanyCode" ... sap:field-control="mandatory"/>
https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.comp.smartfield.SmartField.html

The mandatory property of the entity has to be nullable="false". That's it.
Have a look at the smart field example from your link:
<Property Name="Name" Type="Edm.String" Nullable="false"
MaxLength="30" sap:label="Name" sap:creatable="false"
sap:quickinfo="Property annotation DataFieldWithUrl"
sap:updatable="true" sap:sortable="false" />
Btw. thanks for sharing your smart table example!

From my understanding there are 2 options:
1) Define a specific property as Mandatory --> Nullable="false"
2) Link a property to another property in the entity, the "field-control".
This field control can contain numbers and "7" means mandatory.
The linking from option 2 can be done in the MPC_EXT class (redefine the define method).
The actual value in the "field-control" property is set in the get_entity / get_en
However I am also having an issue with the smarttable. The mandatory fields do not light up red when empty.

Do it in brute force way in the Object Page extension controller.
var oField = this.getView().byId(<FieldId>)
oField.getDataProperty().property.nullable = "false" or "true".
"false" and "true" must be a string.
To convert a boolean to string use <boolean>.toString();

Related

how to hide advance search by defalt in SmartField Value help in UI5?

I'm trying to hide Advance search in value help by default.
When this dialog opens, by default the category and category description Advance search options appears, I want this to be hidden.
Please help on how to approach this issue.
This is what I have
This is what I want: (Advance search to be hidden, not removed altogether)
It seems, you have used the Explored-Example from here
There you can also download the coding. Maybe you need to adjust the paths to the mockdata to get it up and running.
What happens if you try: sap:filterable="false" in your metadata.xml ?
Please see also the corresponding docu.
There it says:
“We notice that we have set sap:filterable="false" for the CURR property.
We do this, since we would otherwise also have a currency code search field in the dialog that we wish to avoid (default of sap:filterable is true).”
Now your adjusted metadata.xml from the SmartField example above could look like:
<EntityType Name="VL_SH_H_CATEGORY" sap:content-version="1">
<Key>
<PropertyRef Name="CATC" />
</Key>
<Property Name="CATC" Type="Edm.String" Nullable="false" MaxLength="4" sap:display-format="UpperCase" sap:label="Category" sap:text="LTXT" sap:filterable="false" />
<Property Name="LTXT" Type="Edm.String" Nullable="false" sap:label="Category Description" sap:filterable="false"/>
</EntityType>
…
Is this what you are looking for ?

The changes to the database were committed successfully, but an error occurred while updating the object - revised

I am using EF in .NET V4.0 in Visual Basic (VS2010) with SQL Compact Edition 4.0. We are building a set of simple forms to maintain some tables. One table 'Companies' is linked to 2 other tables (People,CalibrationInfo) with Companies as the parent table. The Entity Type Definition is:
<EntityType Name="Company">
<Documentation>
<Summary>Provides a list of Companies and shipping addresses.</Summary>
</Documentation>
<Key>
<PropertyRef Name="CompanyID" />
</Key>
<Property Name="CompanyID" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Name="Name" Type="String" MaxLength="100" Unicode="true" FixedLength="false" Nullable="false" />
<Property Name="Address1" Type="String" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="Address2" Type="String" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="Address3" Type="String" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="Telephone" Type="String" MaxLength="30" FixedLength="false" Unicode="true" />
<Property Name="PrimaryContactID" Type="Int32" a:GetterAccess="Public" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Public" Nullable="true" >
<Documentation>
<Summary>Optional Primary Contact ID for the primary contact for this company.</Summary>
</Documentation>
</Property>
<Property Name="Disabled" Type="Boolean" Nullable="false" DefaultValue="false" />
<NavigationProperty Name="Calibrations" Relationship="NWCUDataStoreModel.FK_CalibrationInfo_Company" FromRole="Companies" ToRole="CalibrationInfo" />
<NavigationProperty Name="PrimaryContact" Relationship="NWCUDataStoreModel.FK_Company_PrimaryContact" FromRole="Company" ToRole="Person" />
</EntityType>
The form uses a binding source set to the Company set in the context:
bsCompanies = ctx.Companies.OrderBy("it.Name")
The Binding Source is linked to a Navigation Bar. Pressing the BindingNavigatorAddNewItem button gets a new record created. I enter only the company name tab to the next field and press the Save button. The link to the Primary Contact is set to nothing so there are no other relationships for this record. The Save button executes the following:
RowsSaved = ctx.SaveChanges()
This generates the InvalidOperationException. The Inner exception is:
AcceptChanges cannot continue because the object's key values conflict with another object...
There are no other records in the database with the name set to 'Test'. The exception indicates that the record was saved, but was unable to accept the changes. The record is still marked as Added. Calling ctx.AcceptChanges after this error generates an exception.
If I were doing this directly in code, instead of with BindingSource on a form, it would essentially look like this:
dim company as New Company
company.Name="Test"
company.PrimaryContactID = nothing
ctx.Companies.Add(company)
ctx.Save
I have looked at other examples of this on multipe sites, and have applied any fixes I could find, including setting the PrimaryContact id directly to a the correct Person record ID and setting the PrimaryContact to Nothing. Nothing makes any difference.
I have also deleted the three tables from the model and then reloaded them. No difference.
I have used this same code with no problems in SQL Server, but almost nothing seems to work with SQL Compact edition V4.0. You would think it should not be so difficult to store a single record into a table. If we have to go back to data sets, I have a lot of recoding to do.
Any suggestions or insights appreciated.
Thanks, Neil
BTW, the answer to this was to use Nuget to download Entity Framework 6.0, Entity Framework SQL Server Compact and Microsoft SQL Server Compact 4.0. I then downloaded the EF Framework 5 DB Generator .tt file as the EF 6 version does not work in Visual Studio 2010. You do this from the Add Code Generation menu item, and select Online Templates->EF 5 DBContext Generator... Finally, I modified the file using this Microsoft article: Databinding with WinForms. After that, things started to work. EF 4.0 does not work with SQL Server Compact, out of the box, without the changes described above. Using the ObservableListSource class described in the article also helped with parent-child relationships on forms, which did not work until I switched to this class.

Entity Framework designer custom property does not appear in DDL generation

I have added a custom property to the Properties dialog of the Entity Framework 5 designer through
http://msdn.microsoft.com/en-us/library/microsoft.data.entity.design.extensibility.ientitydesignerextendedproperty(v=vs.103).aspx
This works well, the property appears in the Properties dialog and it is saved in the EDMX file.
Now I'd like to use that property in the DDL generation process. I have edited the T4 template file SSDLToSQL10.tt (found at C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen).
However, the custom property doesn't seem to appear anywhere in the metadata tree. The website (in German)
http://www.databinding.net/en/blog/post/2010/12/13/entity-framework-4-erweiterte-eigenschaften-in-einer-t4-vorlage-verwenden.html
tells me that the extended property should appear in the EntityType.MetadataProperties collection, but this collection contains only the following members:
KeyMembers Members Name NamespaceName Abstract BaseType DataSpace MetadataProperties
None of those is my custom property.
Am I missing something? How can I access the IEntityDesignerExtendedProperty's value in the T4 code generation template?
EDIT: Here is the EDMX part with the custom property:
<edmx:ConceptualModels>
<Schema ...>
....
<EntityType Name="Entity1">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Type="Guid" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="None" />
<Property Type="String" Name="Name" Nullable="false" />
<a:MyNewProperty xmlns:a="http://schemas.tempuri.com/MyNewProperty">True</a:MyNewProperty>
</EntityType>
I guess I have to map that custom property from CSDL to SSDL somehow.
You added the property to the CSDL (conceptual layer) while the DDL is created using the SSDL (store layer). You should be able to access the conceptual model in the SSDLToSQL10.tt but I don't think it is really what you are after. In general your property is not something the EF runtime can really use - I believe it will be just treated as an extension and ignored. If you want to add a property that is supposed to be used by the EF runtime the property must be declared in the CSDL (conceptual layer) and SSDL (store layer) and mapped correctly in the MSL (mapping layer) - with the latter being probably the most difficult.
Unless I am missing what you are trying to achieve you are probably using a wrong extension point. The IEntityDesignerExtendedProperty allows defining custom properties that shows in the property and the model browser windows in the designer but are ignored at runtime. For me it looks like you would like to add a property automatically to your model. For that I would try using the IModelTransformationExtension where you should be given the entire edmx which you will be able to modify at will (i.e. CSDL, SSDL, MSL and add elements (properties) in correct EF xml namespaces). I would try using OnBeforeModelSaved since I believe the model will be saved automatically before trying to generate the database.
I was able to achieve what I want using the edmx:CopyToSSDL=true attribute:
<edmx:ConceptualModels>
<Schema ...>
....
<EntityType Name="Entity1">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Type="Guid" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="None" />
<Property Type="String" Name="Name" Nullable="false" />
<a:MyNewProperty edmx:CopyToSSDL="true"
xmlns:a="http://schemas.tempuri.com/MyNewProperty">
True
</a:MyNewProperty>
</EntityType>
This way, the transformator that generates the SSDL from the CSDL copies the annotation over to the SSDL, so I'm able to access it in the T4 template that generates the DDL SQL file.
If someone is going to use this in Entity Framework 5, please not that there is a bug (http://entityframework.codeplex.com/workitem/702), and you can workaround by using the old EDMX XML namespace:
<a:MyNewProperty edmxv2:CopyToSSDL="true"
xmlns:a="http://schemas.tempuri.com/MyNewProperty"
xmlns:edmxv2="http://schemas.microsoft.com/ado/2008/10/edmx">
True
</a:MyNewProperty>

Reset ADO.NET schema

I modified a schema (set a field to be non-nullable), but when I try to recreate the mapping with ADO.NET I only see the old schema.
The .edmx file looks like this:
<EntityType Name="STG_DW_BUF_CODE_D">
<Key>
<PropertyRef Name="BUF_CODE_KEY" />
</Key>
<Property Name="BUF_CODE_KEY" Type="number" Nullable="false" />
…
<EntityType Name="STG_DW_REGION_D">
<Property Name="REGION_KEY" Type="number" />
The STG_DW_REGION_D view should have Nullable="false" like the view above it.
I can confirm the new schema has this field non-nullable through another SQL application, but I can't get ADO.NET to notice.
I tried erasing the model and recreating it. I tried closing visual studio and starting it up again. It still sees the old schema.
Does anyone know how to reset it? Any suggestions?
This is either a bug in ADO.NET or ODP (Oracle's connection to Linq). If you add a field it will remove the cached schema and pull in a new schema with updated field attributes.

In Entity Framework, getting the value of an identity column after inserting

I'm using EF4. I want to insert a new MyObject into the database. MyObject has two fields:
Id: int (Identity) and
Name: string
As I've seen in documentation Entity Framework is supposed to set MyObject.Id to the value generated by database after the call to SaveChanges() but in my case that doesn't happen.
using (var context = new MyEntities())
{
var myObject = MyObjects.CreateMyObject(0, "something"); // The first parameter is identity "Id"
context.MyObjects.AddObject(myObject);
context.SaveChanges();
return myObject.Id; // The returned value is 0
}
UPDATE:
This happens in one of my entities and others work fine. By the way, I checked and the DB column is identity and StoreGeneratedPattern is set to Identity.
Here is the SSDL. I don't see any difference. The first one isn't working right:
<EntityType Name="OrgUnit">
<Key>
<PropertyRef Name="Srl" />
</Key>
<Property Name="Srl" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="TypeId" Type="smallint" Nullable="false" />
<Property Name="Name" Type="varchar" Nullable="false" MaxLength="80" />
</EntityType>
<EntityType Name="OrgType">
<Key>
<PropertyRef Name="Srl" />
</Key>
<Property Name="Srl" Type="smallint" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Title" Type="varchar" Nullable="false" MaxLength="120" />
<Property Name="Options" Type="int" Nullable="false" />
</EntityType>
The update is done successfully in the database and the identity is generated but the entity object is not updated with the new identity.
In that case, you EF model is probably not up to date - EF should automagically get your new ID from the database. Try refreshing your EF model.
Your identity column's properties should look like this in your EDMX model:
If you're using Oracle Entity Framework 4 Provider, like I do, from ODP.NET, there is a bug in Designer. Just selecting the Identity value in drop down box will not do. It will annotate the conceptual property in conceptual model with
annotation:StoreGeneratedPattern="Identity"
like in
<Property Type="Int32" Name="Id" Nullable="false" cg:SetterAccess="Private" annotation:StoreGeneratedPattern="Identity" />
But, it will fail to do the same for Storage Model, ie. you need to do it manually. Find the Property (in my case ID) in EntityType of interest and add StoreGeneratedPattern="Identity".
<EntityType Name="PROBLEMI">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="number" Nullable="false" Precision="10" StoreGeneratedPattern="Identity" />
I'm not aware of the same bug in SQL EF provider 'cos I didn't use it.
This should "just work." Make sure the DB column actually is IDENTITY, and that StoreGeneratedPattern is set to Identity in EDMX.
wow! that was a nightmare but at last I solved it, although I didn't understand what the problem was. Maybe this helps someone with the same problem.
Generate the script for creating the table and its data.
Drop the table.
Run the script.
If you are using Linq To Entities, and get this error even if you followed the advices of marc_s (that are really good), you should look at your entites directly in the edmx (xml view) and check if they have the following attribute :
<EntityType Name="MyEntity">
<Key>
<PropertyRef Name="pk" />
</Key>
<Property Name="pk" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="value" Type="float" Nullable="false" />
</EntityType>
The StoreGeneratedPattern="Identity" is also required.
Try using refresh method after Save Changes, it has been documented in MSDN
"To ensure that objects on the client have been updated by data source-side logic, you can call the Refresh method with the StoreWins value after you call SaveChanges."
http://msdn.microsoft.com/en-us/library/bb336792.aspx
Though i feel what #Craig has suggested might also work.
I ran into this today. The difference though was I was using an insert function, where the above person doesn't specify that. What I had to do was make my insert function stored procedure return SCOPE_IDENTITY() and use a result binding for the id returned.
Fixed my issue.