I am unable to populate a JavaFX TableView object with my own data. I have attempted to modify the code found here to suit the needs of my program.
I added the table used in that tutorial, and it displays properly. I copied that code to create a second table, but cannot get my data to display in that second table.
I believe that I have properly modified the code to accept data from my SNMPInterface class. I attempt to populate my table with static data, and later with data read in from a file. Neither process works, though either will create the columns with the proper headers.
My full project can be found on GitHub.
Initially, I create a TableView object of 'SNMPInterface' class objects:
private TableView< SNMPInterface > interfaceTableView = new TableView<>();
I then create an ObservableList of SNMPInterface objects:
private final ObservableList< SNMPInterface > interfaceData =
FXCollections.observableArrayList(
new SNMPInterface( "99", "testlo" ),
new SNMPInterface( "98", "testeth1" ),
new SNMPInterface( "97", "testeth2" ),
new SNMPInterface( "96", "testbond0" )
);
Later, I create a column for the 'ifIndex' data member:
TableColumn< SNMPInterface, String > ifIndexCol = new TableColumn<>( "Index" );
ifIndexCol.setCellValueFactory( new PropertyValueFactory<>( "ifIndex" ) );
...and the second column for 'ifDescr':
TableColumn ifDescrCol = new TableColumn( "Description" );
ifDescrCol.setCellValueFactory( new PropertyValueFactory<>( "ifDescr" ) );
I then try to add it to the GridPane (named rootNode):
interfaceTableView.setItems( interfaceData );
interfaceTableView.getColumns().setAll( ifIndexCol, ifDescrCol );
rootNode.add( interfaceTableView, 0, 7, 2, 1 );
...but that does not work.
I have a loop to verify that the data is available to the method, and a second that verifies that the data is properly read in from the files. Both containers seem to have valid data, but neither makes it into my table.
My table seems to be effectively the same as the tutorial table, but obviously I am making an error somewhere. Does anyone see where my error is?
The getters and setters on the SNMPInterface class that you use for input to PropertyValueFactory should be marked public, not no modifier (otherwise the reflection logic inherent in the PropertyValueFactory won't find them).
public static class SNMPInterface {
private final SimpleStringProperty ifIndex;
private final SimpleStringProperty ifDescr;
SNMPInterface( String ifIndex, String ifDescr ) {
this.ifIndex = new SimpleStringProperty( ifIndex );
this.ifDescr = new SimpleStringProperty( ifDescr );
}
public String getIfIndex() {
return ifIndex.get();
}
public void setIfIndex( String index ) {
ifIndex.set( index );
}
public String getIfDescr() {
return ifDescr.get();
}
public void setIfDescr( String descr ) {
ifDescr.set( descr );
}
}
Related
I currently have stored procedures for Oracle SQL, version 18c, for both inserting and fetching multiple rows of data from one parent table and one child table, being called from my Java Spring Boot application. Everything works fine, but it is extremely slow, for only a few rows of data.
When only inserting 70 records between the two, it takes up to 267 seconds into empty tables. Fetching that same data back out takes about 40 seconds.
Any help would be greatly appreciated or if there is any additional information needed from me.
Below is a cut down and renamed version of my stored procedures for my parent and child tables, actual parent table has 32 columns and child has 11.
PROCEDURE processParentData(
i_field_one varchar2,
v_parent_id OUT number) is
v_new PARENT%ROWTYPE;
BEGIN
v_new.id := ROW_SEQUENCE.nextval;
v_new.insert_time := systimestamp;
v_new.field_one := i_field_one;
insert into PARENT values v_new;
v_parent_id := v_new.id;
END;
PROCEDURE readParentData(
i_field_one IN varchar2,
v_parent OUT SYS_REFCURSOR) AS
BEGIN
OPEN v_parent FOR select h.* from PARENT h
where h.field_one = i_field_one;
END;
PROCEDURE processChild(
i_field_one varchar2,
i_parent_id number) is
v_new CHILD%ROWTYPE;
BEGIN
v_new.id := ROW_SEQUENCE.nextval;
v_new.insert_time := systimestamp;
v_new.field_one := i_field_one;
v_new.parent_id := i_parent_id;
insert into CHILD values v_new;
END;
PROCEDURE readChild(
i_parent_id IN number,
v_child OUT SYS_REFCURSOR) AS
BEGIN
OPEN v_child FOR select h.* from CHILD h
where h.parent_id = i_parent_id;
END;
For my Java code I am using Spring JDBC. After I get the parent data, I then fetch each child data by looping through the parent data and calling readChild with the parent ID for each.
var simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("PARENT_PACKAGE")
.withProcedureName("processParentData");
SqlParameterSource sqlParameterSource = new MapSqlParameterSource()
.addValue("i_field_one", locationId)
.addValue("v_parent_id", null);
Map<String, Object> out = simpleJdbcCall.execute(sqlParameterSource);
var stopId = (BigDecimal) out.get("v_parent_id");
return stopId.longValue();
var simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("PARENT_PACKAGE")
.withProcedureName("readParentData")
.returningResultSet("v_parent", BeanPropertyRowMapper.newInstance(Parent.class));
SqlParameterSource sqlParameterSource = new MapSqlParameterSource()
.addValue("i_field_one", location.getId());
Map<String, Object> out = simpleJdbcCall.execute(sqlParameterSource);
return (List<Parent>) out.get("v_parent");
UPDATE 1: As I know and have tested, using the same data and tables, if I use pure JDBC or JPA/Hibernate for inserting and fetching to the tables directly and avoid using stored procedures, then the whole process of inserting and fetching only takes a few seconds.
The issue is, at the company I work at, they have set a policy that all applications going forward are not allowed to have direct read/write access to the database and everything must be done through stored procedures, they say for security reasons. Meaning I need to workout how to do the same thing we have been doing for years with direct read/write access, now with only using Oracle stored procedures.
UPDATE 2: Adding my current Java code for fetching the child data.
for (Parent parent : parents) {
parent.setChilds(childRepository.readChildByParentId(parent.getId()));
}
public List<Child> readChildByParentId(long parentId) {
var simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("CHILD_PACKAGE")
.withProcedureName("readChild")
.returningResultSet("v_child", BeanPropertyRowMapper.newInstance(Child.class));
SqlParameterSource sqlParameterSource = new MapSqlParameterSource()
.addValue("i_parent_id ", parentId);
Map<String, Object> out = simpleJdbcCall.execute(sqlParameterSource);
return (List<Child>) out.get("v_child");
}
The problem is that the insert you are trying to perform using the stored procedure is not optimized, because you are calling the database every time you try to insert a row.
I strongly recommend you to transform the data to XML (for example, you can also use CSV) and pass it to the procedure, then loop over it and perform the inserts that you need.
Here is an example made using Oracle:
CREATE OR REPLACE PROCEDURE MY_SCHEMA.my_procedure(xmlData clob) IS
begin
FOR CONTACT IN (SELECT *
FROM XMLTABLE(
'/CONTACTS/CONTACT' PASSING
XMLTYPE(contactes)
COLUMNS param_id FOR ORDINALITY
,id NUMBER PATH 'ID'
,name VARCHAR2(100) PATH 'NAME'
,surname VARCHAR2(100) PATH 'SURNAME'
))
LOOP
INSERT INTO PARENT_TABLE VALUES CONTACT.id, CONTACT.name, CONTACT.surname;
end loop;
end;
The XML, you can use a String to pass the data to the procedure:
<CONTACTS>
<CONTACT>
<ID>1</ID>
<NAME>Jonh</NAME>
<SURNAME>Smith</SURNAME>
</CONTACT>
<CONTACTS>
For my Java code I am using Spring JDBC. After I get the parent data, I then fetch each child data by looping through the parent data and calling readChild with the parent ID for each.
Instead of fetching child data in loop, you can modify your procedure to accept list of parent id and return all the data in one call.
It will be helpful if you share spring boot for loop code as well.
Update
Instead of fetching single parent details, you should have update your code like this. Also you have to update your procedure as well.
List<Long> parents = new ArrayList<>();
for (Parent parent : parents) {
parents.add(parent.getId());
}
You can use java streams but that is secondary things.
Now you have to modify your procedure and method to accept multiple parent ids.
List<Child> children = childRepository.readreadChildByParentId(parents);
public List<Child> readChildByParentId(long parentId) {
var simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("CHILD_PACKAGE")
.withProcedureName("readChild")
.returningResultSet("v_child", BeanPropertyRowMapper.newInstance(Child.class));
SqlParameterSource sqlParameterSource = new MapSqlParameterSource()
.addValue("i_parent_id ", parentId);
Map<String, Object> out = simpleJdbcCall.execute(sqlParameterSource);
return (List<Child>) out.get("v_child");
}
After having all the children you can set parent children via java code.
P.S.
Could you please check if you fetch parents with children if parent is coming from the database?
Your performance problems are probably related with the number of operations performed against the database: you are iterating in Java your collections, and interacting with the database in every iteration. You need to minimize the number of operations performed.
One possible solution can be the use of the standard STRUCT and ARRAY Oracle types. Please, consider for instance the following example:
public static void insertData() throws SQLException {
DriverManagerDataSource dataSource = ...
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
SimpleJdbcCall insertDataCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("parent_child_pkg")
.withProcedureName("insert_data")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("p_parents")
.declareParameters(
new SqlParameter("p_parents", OracleTypes.ARRAY, "PARENT_ARRAY")
);
OracleConnection connection = null;
try {
connection = insertDataCall
.getJdbcTemplate()
.getDataSource()
.getConnection()
.unwrap(OracleConnection.class)
;
List<Parent> parents = new ArrayList<>(100);
Parent parent = null;
List<Child> chilren = null;
Child child = null;
for (int i = 0; i < 100; i++) {
parent = new Parent();
parents.add(parent);
parent.setId((long) i);
parent.setName("parent-" + i);
chilren = new ArrayList<>(1000);
parent.setChildren(chilren);
for (int j = 0; j < 1000; j++) {
child = new Child();
chilren.add(child);
child.setId((long) j);
child.setName("parent-" + j);
}
}
System.out.println("Inserting data...");
StopWatch stopWatch = new StopWatch();
stopWatch.start("insert-data");
StructDescriptor parentTypeStructDescriptor = StructDescriptor.createDescriptor("PARENT_TYPE", connection);
ArrayDescriptor parentArrayDescriptor = ArrayDescriptor.createDescriptor("PARENT_ARRAY", connection);
StructDescriptor childTypeStructDescriptor = StructDescriptor.createDescriptor("CHILD_TYPE", connection);
ArrayDescriptor childArrayDescriptor = ArrayDescriptor.createDescriptor("CHILD_ARRAY", connection);
Object[] parentArray = new Object[parents.size()];
int pi = 0;
for (Parent p : parents) {
List<Child> children = p.getChildren();
Object[] childArray = new Object[children.size()];
int ci = 0;
for (Child c : children) {
Object[] childrenObj = new Object[2];
childrenObj[0] = c.getId();
childrenObj[1] = c.getName();
STRUCT childStruct = new STRUCT(childTypeStructDescriptor, connection, childrenObj);
childArray[ci++] = childStruct;
}
ARRAY childrenARRAY = new ARRAY(childArrayDescriptor, connection, childArray);
Object[] parentObj = new Object[3];
parentObj[0] = p.getId();
parentObj[1] = p.getName();
parentObj[2] = childrenARRAY;
STRUCT parentStruct = new STRUCT(parentTypeStructDescriptor, connection, parentObj);
parentArray[pi++] = parentStruct;
}
ARRAY parentARRAY = new ARRAY(parentArrayDescriptor, connection, parentArray);
Map in = Collections.singletonMap("p_parents", parentARRAY);
insertDataCall.execute(in);
connection.commit();
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
} catch (Throwable t) {
t.printStackTrace();
connection.rollback();
} finally {
if (connection != null) {
try {
connection.close();
} catch (Throwable nested) {
nested.printStackTrace();
}
}
}
}
Where:
CREATE OR REPLACE TYPE child_type AS OBJECT (
id NUMBER,
name VARCHAR2(512)
);
CREATE OR REPLACE TYPE child_array
AS TABLE OF child_type;
CREATE OR REPLACE TYPE parent_type AS OBJECT (
id NUMBER,
name VARCHAR2(512),
children child_array
);
CREATE OR REPLACE TYPE parent_array
AS TABLE OF parent_type;
CREATE SEQUENCE PARENT_SEQ INCREMENT BY 1 MINVALUE 1;
CREATE SEQUENCE CHILD_SEQ INCREMENT BY 1 MINVALUE 1;
CREATE TABLE parent_table (
id NUMBER,
name VARCHAR2(512)
);
CREATE TABLE child_table (
id NUMBER,
name VARCHAR2(512),
parent_id NUMBER
);
CREATE OR REPLACE PACKAGE parent_child_pkg AS
PROCEDURE insert_data(p_parents PARENT_ARRAY);
END;
CREATE OR REPLACE PACKAGE BODY parent_child_pkg AS
PROCEDURE insert_data(p_parents PARENT_ARRAY) IS
l_parent_id NUMBER;
l_child_id NUMBER;
BEGIN
FOR i IN 1..p_parents.COUNT LOOP
SELECT parent_seq.nextval INTO l_parent_id FROM dual;
INSERT INTO parent_table(id, name)
VALUES(l_parent_id, p_parents(i).name);
FOR j IN 1..p_parents(i).children.COUNT LOOP
SELECT child_seq.nextval INTO l_child_id FROM dual;
INSERT INTO child_table(id, name, parent_id)
VALUES(l_child_id, p_parents(i).name, l_parent_id);
END LOOP;
END LOOP;
END;
END;
And Parent and Child are simple POJOs:
import java.util.ArrayList;
import java.util.List;
public class Parent {
private Long id;
private String name;
private List<Child> children = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
}
public class Child {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Please, forgive for the code legibility and incorrect error handling, I will improve the answer later including some information about obtaining the data as well.
The times you mention are horrible indeed. A big boost forward in performance will be to work set based. This means reducing the row by row database calls.
Row by row is synonymous for slow, especially when network round trips are involved.
One call to get the parent.
One call to get the set of children and process them. The jdbc fetch size is a nice tunable here. Give it a chance to work for you.
You do not need to use DYNAMIC SQL OPEN v_parent FOR and also it is not clear how the view v_parent is defined.
Try to check exec plan of this query:
FOR select h.* from PARENT h where h.field_one = ?;
Usually returning recordset via SYS_REFCURSOR increases performance when you return more (let's say) than 10K records.
The SimpleJdbcCall object can be reused in your scenario as only the parameters changes. The SimpleJdbcCall object compiles the jdbc statement on the first invocation. It does some meta-data fetching and it interacts with the Database for that. So, having separate objects would mean fetching same metadata that many times which is not needed.
So, I suggest to initialise all the 4 SimpleJdbcCall objects in the very beginning and then work with them.
var insertParentJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("PARENT_PACKAGE")
.withProcedureName("processParentData");
var readParentJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("PARENT_PACKAGE")
.withProcedureName("readParentData")
.returningResultSet("v_parent", BeanPropertyRowMapper.newInstance(Parent.class));
var insertChildJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("CHILD_PACKAGE")
.withProcedureName("processChildData");
var readChildJdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("CHILD_PACKAGE")
.withProcedureName("readChild")
.returningResultSet("v_child", BeanPropertyRowMapper.newInstance(Child.class));
it might be a simple question or even impossible without any kind of Interface (Arrays, Maps etc.) but I would like to know if there's any possibility of converting an object name to String so I can pass as argument. I have two classes Paciente and Sintomas with multiple objects that I need to pass as argument to a function but I don't want to use arrays (it must be like that) and I can't figure any other way of doing so without manually make an insert for each one.
Paciente Paciente1 = new Paciente("001", "Ana Melo", 33, "");
Paciente Paciente2 = new Paciente("002", "Rui Costa", 13, "");
Paciente Paciente3 = new Paciente("003", "Joana Martins", 85, "");
Paciente Paciente4 = new Paciente("004", "Pedro Torres", 53, "");
Paciente Paciente5 = new Paciente("005", "Ana Gomes", 93, "");
Paciente Paciente6 = new Paciente("006", "Jorge Costa", 56, "");
Sintomas Sintoma1 = new Sintomas("001", "febre");
Sintomas Sintoma2 = new Sintomas("001", "dores");
Sintomas Sintoma3 = new Sintomas("001", "machas");
Sintomas Sintoma4 = new Sintomas("002", "febre");
Sintomas Sintoma5 = new Sintomas("002", "manchas");
Sintomas Sintoma6 = new Sintomas("003", "febre");
Sintomas Sintoma7 = new Sintomas("003", "dores");
Sintomas Sintoma8 = new Sintomas("004", "febre");
Sintomas Sintoma9 = new Sintomas("006", "manchas");
Sintomas Sintoma10 = new Sintomas("006", "dores");
// now I would like to pass to a function as argument something like this:
for(int i = 0 ; i < 6 ; i++)
kSession.insert("Paciente"+(i+1));
// instead of making
kSession.insert(Paciente1);
kSession.insert(Paciente2);
kSession.insert(Paciente3);
// and so on.
Something like this should work(asuming you mean no array because of size constraints), note that there has to be somewhere you add the data, it's also possible to load it from a txt or something, but it has to be defined at some point
List<Paciente> pacientes = new ArrayList<>(); // no size constraints, automatically expands if too small
pacientes.add(new Paciente("", "", ""));
for (Paciente paciente : pacientes) { // loop all Patientes in pacientes
kSession.insert(paciente); // add a paciente to the session, for every entry
}
ofcource same can be done for any class, or object
It all really comes down to, how do you wish to store and access the data, and where do you need to store and access it. Using ArrayList and Map's offer the utility of easily changing the size and content of a list of data, but as any data it must be initially inserted
As a side note if the patients have an ID then using a Map
Map<String, Paciente> pacientes = new HashMap<>();
provides a way to acces the patiens very fast, and the TreeMap structure is sorted on key, should that be needed.
Other options could be
Wrapper classes that manage the data, will work similarily to an ArrayList<> but you can define, rules for adding, deleting, and such from the list.
public class Wrapper{
private List<Paciente> pacientes = new ArrayList<>();
public void addPaciente(Paciente paciente){
if(!this.pacientes.contains(paciente)) // prevent multi entries
paciente.add(paciente);
}
public void addPacientes(List<Paciente> pacientes){
for(Paciente paciente : pacientes) // add all patients using the add method
this.addPaciente(paciente);
}
public List<Paciente> getPacientes(){
return this.pacientes;
}
}
You can then add the patients to the kSession, as earlier described
Finally, there is no reason why Paciente, can have the list of Sintomas, such that
public class Paciente{
private List<Sintomas> sintomas = new ArrayList<>();
public addSintomas(Sintomas sintomas){
if(!this.sintomas.contains(sintomas))
this.sintomas.add(sintomas);
}
// rest is the same principle as above in "Wrapper"
}
This way you can get a Paciente, and add a Sintomas, and then when you wish to check a Pacientes Sintomas you can just get the list of Sintomas from that Paciente
I need to make a programm in JavaFX where I need to manage a movie library. I have a tableview that is filled by an observable list. Then I made bindings between the Properties and the Textboxes or Labels next to the tableview. Now the problem is, I have also pictures that are related to the movies, like cinema posters. and at the moment I just use a hardcoded one:
imgPoster = new Image(getClass().getResourceAsStream("../resources/images/posters/" + 5 + ".jpg"));
In the datafile there is one column with the ID of the movie and the same number is also the picture for it. So I need to replace that "5" in the sample code with a binding or so that it actively changes the picture as soon as I click on a row in the tableview.
How do I do that?
edit:
After the first comment i did that:
imgOscars = new Image(getClass().getResourceAsStream("../resources/images/oscar/Oscar-logo.png"));
oscars = new ImageView(imgOscars);
oscars.setPreserveRatio(true);
oscars.setFitHeight(45);
but question stays
Either add a listener to the selected item property in the table (I am just guessing at the model you are using for the table):
TableView<Movie> table = ... ;
table.getSelectionModel().selectedItemProperty().addListener((obs, oldSelectedMovie, newSelectedMovie) -> {
if (newSelectedMovie == null) {
oscars.setImage(null);
} else {
// get image from new selection
Image image = new Image(getClass().getResourceAsStream("../resources/images/oscar/"+newSelectedMoviegetId()+".png"));
oscars.setImage(image);
}
});
or use a binding:
oscars.imageProperty().bind(Bindings.createObjectBinding(() -> {
if (table.getSelectionModel().getSelectedItem() == null) {
return null ;
} else {
Movie selected = table.getSelectionModel().getSelectedItem();
return new Image(getClass().getResourceAsStream("../resources/images/oscar/"+selected.getId()+".png")); ;
},
table.getSelectionModel().selectedItemProperty());
I have a class, MAN. I want to add an individual, jack, with properties:
hasage="50"
hasadress="france"
How can I create my individual jack and add properties to him and save them into my file database.owl? Here is the connection. I use Eclipse and the Jena API.
JenaOWLModel owlModel ;
OntModel model;
owlModel = ProtegeOWL.createJenaOWLModelFromURI("file:///C:/database.owl");
model = owlModel.getOntModel();
i am begging you to help me , it still fiew days for my thesis defence this CODE work perfectly i can save individuals in my file.owl BUT i couldnt add properties to those individuals and save them with.
please help me what should i do , i am realy worried thanks a lot in advance
public class testins {
static JenaOWLModel owlModel ;
public static void main(String[] args) {
OntModel model;
javax.swing.JDialog jDialog1 = new javax.swing.JDialog();
try{
owlModel = ProtegeOWL.createJenaOWLModelFromURI("file:///D:/file.owl");// the link of my owl file
model = owlModel.getOntModel();
JOptionPane.showMessageDialog(jDialog1,
"loaded with success","Information",JOptionPane.INFORMATION_MESSAGE);
}
catch(Exception e){
JOptionPane.showMessageDialog(jDialog1,
"error",
"Information",
JOptionPane.INFORMATION_MESSAGE);
}
OWLNamedClass theAlert = owlModel.getOWLNamedClass("Alert"); //my class Alert
theAlert.createOWLIndividual("indivname1"); //i add here an indevidual
theAlert.createOWLIndividual("indivname2"); //i add here another indevidual
// now how to add to those two Individuals properties ?? each individual has 2
// properties , the property witch its name est_evaluer and the second est_analyser those
// to properties will contain values so here is my problem how to add those values to an
// individual and save all of them
Collection errors ;
String fileName ;
fileName= ("D:/file.owl");
errors = new ArrayList();
//here i'll save it and it work ,it mean that i find in my file "file.owl"
//individuals i added witch are "indivname1" and "indivname2" in my class ALERT
// so now my problem is how to add properties to those indiviuals i add , and save them also
try{ owlModel.save(new File(fileName).toURI(), FileUtils.langXMLAbbrev, errors);
System.out.println("File saved with " + errors.size() + " errors.");
}
catch(Exception e){
}
}
}
You didn't say what the namespace you are using is. So I'm going to assume http://example.org/example#, adjust as necessary.
String NS = "http://example.org/example#";
// create ex:Man class
OntClass man = model.createClass( NS + "Man" );
// create individual ex:jack
Individual jack = model.createIndividual( NS + "jack", man );
// create some properties - probably better to use FOAF here really
DatatypeProperty age = model.createDatatypeProperty( NS + "age" );
DatatypeProperty address = model.createDatatypeProperty( NS + "address" );
jack.addProperty( age, model.createTypedLiteral( 50 ) )
.addProperty( address, model.createLiteral( "France" ) );
I can't seem to update an existing record in my table using a strongly-typed dataset. I can add a new record, but if I make changes to an existing record it doesn't work.
Here is my code:
private void AddEmplMaster()
{
dsEmplMast dsEmpMst = new dsEmplMast();
SqlConnection cn = new SqlConnection();
cn.ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["cn.ConnectionString"];
SqlDataAdapter da1 = new SqlDataAdapter("SELECT * FROM UPR00100", cn);
SqlCommandBuilder cb1 = new SqlCommandBuilder(da1);
da1.Fill(dsEmpMst.UPR00100);
DataTable dtMst = UpdateEmpMst(dsEmpMst);
da1.Update(dsEmpMst.UPR00100);
}
This procedure is called from above to assign the changed fields to a record:
private DataTable UpdateEmpMst(dsEmplMast dsEmpMst)
{
DataTable dtMst = new DataTable();
try
{
dsEmplMast.UPR00100Row empRow = dsEmpMst.UPR00100.NewUPR00100Row();
empRow.EMPLOYID = txtEmplId.Text.Trim();
empRow.LASTNAME = txtLastName.Text.Trim();
empRow.FRSTNAME = txtFirstName.Text.Trim();
empRow.MIDLNAME = txtMidName.Text.Trim();
empRow.ADRSCODE = "PRIMARY";
empRow.SOCSCNUM = txtSSN.Text.Trim();
empRow.DEPRTMNT = ddlDept.SelectedValue.Trim();
empRow.JOBTITLE = txtJobTitle.Text.Trim();
empRow.STRTDATE = DateTime.Today;
empRow.EMPLOYMENTTYPE = "1";
dsEmpMst.UPR00100.Rows.Add(empRow);
}
catch { }
return dtMst;
}
Thank you
UPDATE:
Ok I figured it out. In my UpdateEmpMst() procedure I had to check if the record exists then to retrieve it first. If not then create a new record to add. Here is what I added:
try
{
dsEmplMast.UPR00100Row empRow;
empRow = dsEmpMst.UPR00100.FindByEMPLOYID(txtEmplId.Text.Trim());
if (empRow == null)
{
empRow = dsEmpMst.UPR00100.NewUPR00100Row();
dsEmpMst.UPR00100.Rows.Add(empRow);
}
then I assign my data to the new empRow I created and updates fine.
In order to edit an existing record in a dataset, you need to access a particular column of data in a particular row. The data in both typed and untyped datasets can be accessed via the following:
With the indices of the tables, rows, and columns collections.
By passing the table and column names as strings to their respective collections.
Although typed datasets can use the same syntax as untyped datasets, there are additional advantages to using typed datasets. For more information, see the "To update existing records using typed datasets" section below.
To update existing records in either typed or untyped datasets
Assign a value to a specific column within a DataRow object.
The table and column names of untyped datasets are not available at design time and must be accessed through their respective indices.