EntityState.Unchanged vs EntityState.Modified with no actual modifications - entity-framework-5

Using EF5 winforms, I want to work out whether the data has changed in my context.
My problem is that EntityState.Modified will be true if DetectChanges has been called regardless of whether any value has changed.
To do this I am using the following code snippet
foreach (var e in Db.ChangeTracker.Entries())
{
switch (e.State)
{
case EntityState.Unchanged :
break;
case EntityState.Deleted:
break;
case EntityState.Added:
break;
case EntityState.Modified:
var original = this.enumerateOriginalValues(e);
var current = this.enumerateCurrentValues(e);
if (original == current) sChanges = "No Changes";
else sChanges = string.Format("Was: {0} Is: {1}", original, current);
break;
}
// build string indicating No Changes or UnChanged
s = string.Format("{0} \r\n {1} {2} {3},{4}", s, sType, sKey, sState, sChanges);
}
Is there a better way to find out whether the context has changes?
[Update]
At Gert's suggestion I put a break in a setter property. I found the following procedure in the call stack.
The qry.Load line is causing the setter to fire.
public override void Refresh()
{
try
{
try
{
if (base.bindingSource.DataSource != null)
{
var per = (Person)base.bindingSource.Current;
this.SaveChangesIfNeeded();
}
DbSet<Person> dset = base.Context.People;
if (this.QuickSearch == null)
{
this.QuickSearch ="";
}
IQueryable<Person> qry;
if (this._organisationId == 0)
{
qry =
dset.Where(
p => p.LastName.Contains(this.QuickSearch) || p.FirstName.Contains(this.QuickSearch));
}
else
{
qry =
dset.Where(
p =>
(p.LastName.Contains(this.QuickSearch) || p.FirstName.Contains(this.QuickSearch)) &&
(p.Organisation.Id == this._organisationId));
}
qry.Load(); // Setter is called here
base.bindingSource.DataSource = dset.Local.ToBindingList();
}
catch (Exception ex)
{
DialogResult dialogResult = MessageBox.Show(ex.Message);
throw;
}
}
catch (Exception ex)
{
HandleException.Show(ex);
}
}
[update] The break also occurs when the navigation buttons are clicked. Here is the call stack.
> SBD.Syrius.DomainClasses.dll!SBD.Syrius.DomainClasses.Person.Title.set(string value) Line 537 C#
[Native to Managed Transition]
System.dll!System.ComponentModel.ReflectPropertyDescriptor.SetValue(object component, object value) + 0x197 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindToObject.SetValue(object value) + 0x8a bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.PullData(bool reformat, bool force) + 0x26e bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingManagerBase.PullData(out bool success) + 0x118 bytes
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.CurrencyManager_PullData() + 0x2f bytes
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.EndCurrentEdit() + 0x27 bytes
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.ChangeRecordState(int newPosition, bool validating, bool endCurrentEdit, bool firePositionChange, bool pullData) + 0xf3 bytes
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.Position.set(int value) + 0x5b bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingNavigator.OnMoveNext(object sender, System.EventArgs e) + 0x2b bytes
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.HandleClick(System.EventArgs e) + 0xb6 bytes
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.HandleMouseUp(System.Windows.Forms.MouseEventArgs e) + 0x237 bytes
System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.OnMouseUp(System.Windows.Forms.MouseEventArgs mea) + 0xef bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x48b bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0xe14 bytes
System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.WndProc(ref System.Windows.Forms.Message m) + 0x8c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x14c bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x681 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x57c bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x6f bytes
SBD.Syrius.UI.exe!SBD.Syrius.UI.Program.Main(string[] args) Line 57 + 0x9 bytes C#
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x66 bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x8d bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x285 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x9 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x57 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x51 bytes
[Native to Managed Transition]

Related

Sending an array of primitive types over a ClientRPC call

I am trying to send an array of various basic types over the Network using the ClientRpc attribute. The documentation states, that I can send these over the Network without problems:
basic types (byte, int, float, string, UInt64, etc)
arrays of basic types
However, it seems holding them mixed together in an object[] array does not work. I have the following example:
[Command]
void CmdForwardEvent(string eventName, object[] args) {
Debug.Log ("Broadcasting event: " + eventName);
foreach (var o in args) {
Debug.Log ("arg-class: " + o.GetType() + ": " + o);
}
RpcForwardEvent (eventName, args);
}
[ClientRpc]
void RpcForwardEvent(string eventName, object[] args) {
Debug.Log ("Received event " + eventName);
foreach (var o in args) {
Debug.Log ("arg-class: " + o.GetType() + ": " + o);
}
}
void Update() {
if (Input.GetKeyDown (KeyCode.P)) {
CmdForwardEvent("Testevent", new object[]{"some string", 1, false});
}
}
On the server, I get the output
Broadcasting event: Testevent
arg-class: System.String: some string
arg-class: System.Int32: 1
arg-class: System.Boolean: false
On the client, this arrives without any errors:
Received event: Testevent
arg-class: System.Object: System.Object
arg-class: System.Object: System.Object
arg-class: System.Object: System.Object
How can I send various amounts of arguments with different basic types over a ClientRpc call?
A possible workaround would be to manually serialize the array and send it as byte[]:
// new code
private BinaryFormatter bf = new BinaryFormatter();
private byte[] objectToBytes(object os) {
MemoryStream stream = new MemoryStream ();
bf.Serialize (stream, os);
return stream.ToArray ();
}
private object bytesToObject(byte[] bytes) {
MemoryStream stream = new MemoryStream (bytes);
return bf.Deserialize (stream);
}
// modified code:
[Command]
void CmdForwardEvent(string eventName, byte[] argsAsBytes) {
object[] args = bytesToObject(argsAsBytes) as object[]; // deserialize
Debug.Log ("Broadcasting event: " + eventName);
foreach (var o in args) {
Debug.Log ("arg-class: " + o.GetType() + ": " + o);
}
RpcForwardEvent (eventName, argsAsBytes);
}
[ClientRpc]
void RpcForwardEvent(string eventName, byte[] argsAsBytes) {
object[] args = bytesToObject(argsAsBytes) as object[]; // deserialize
Debug.Log ("Received event " + eventName);
foreach (var o in args) {
Debug.Log ("arg-class: " + o.GetType() + ": " + o);
}
}
void Update() {
if (Input.GetKeyDown (KeyCode.P)) {
// serialize
byte[] bytes = objectToBytes(new object[]{"some string", 1, false});
CmdForwardEvent("Testevent", bytes);
}
}
output on client and server side are the same then, as expected.

Downloading a file using JSF

Hi I am trying to download a file from server but at the end of my process I end up with only numbers and some weird characters on my browser. It's not downloading the file. I am using seam and JSF 1.2.
Here is my code:
public void writeBytesToResponse(UploadDefinition _instance, String path) {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context .getExternalContext().getResponse();
try {
byte[] bytes = getFile(path);
response.reset();
response.setContentType(ContentType.PDF.getLabel());
response.setContentLength(bytes.length);
response.setHeader("Content-disposition", "attachment; filename=\"" + _instance.getFileName() + "\"");
OutputStream outputStream = response.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
context.responseComplete();
} catch (Exception ex) {
ex.printStackTrace();
}
}
#SuppressWarnings("resource")
public byte[] getFile(String filePath) throws FileNotFoundException, IOException {
File file = new File(filePath);
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
throw new IOException("File is too large " + file.getName());
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file " + file.getName());
}
is.close();
return bytes;
}
Here I call the method:
public void downloadFile() {
writeBytesToResponse(ud, path);
}
I got the answer, I was using <a4j:commandButton> on jsf and I changed it to <h:commandButton> then it worked. The point is not to use ajax.

Use of dbms_lock inconsistent using jdbc

Why does the protected Java code execute in more then one thread at a time?
Thread-1 - protected code iteration 0
Thread-0 - protected code iteration 0
Thread-1 - protected code iteration 1
Thread-0 - protected code iteration 1
Thread-0 - protected code iteration 2
Thread-1 - protected code iteration 2
Thread-1 - protected code iteration 3
Thread-0 - protected code iteration 3
Run it enough times it can execute as expected.
public class DbmsLockTest implements Runnable {
Connection con; String key; int timeout;
public DbmsLockTest(Connection con, String key, int timeout) {
this.con = con; this.key = key; this.timeout = timeout;
}
public static void log(String str) {
System.out.println(new Date() + " - "
+ Thread.currentThread().getName() + " - " + str);
}
#Override
public void run() {
lockKey(con, key, timeout);
}
public static void lockKey(Connection con, String key, int timeout) {
log("start lockKey " + " key: " + key);
CallableStatement cStmt = null;
int rc = 0;
try {
StringBuilder sql = new StringBuilder(500);
sql.append("DECLARE");
sql.append(" v_lockhandle VARCHAR2(200);");
sql.append("BEGIN");
sql.append(" dbms_lock.allocate_unique(lockname => ?, lockhandle => v_lockhandle);");
sql.append(" ? := dbms_lock.request(lockhandle => v_lockhandle, lockmode => 6,");
sql.append(" timeout => ?, release_on_commit =>true);");
sql.append(" ? := v_lockhandle;");
sql.append("END;");
String lockKey = "LockKey-" + key;
cStmt = con.prepareCall(sql.toString());
cStmt.setString(1, lockKey);
cStmt.registerOutParameter(2, Types.NUMERIC);
cStmt.setInt(3, timeout);
cStmt.registerOutParameter(4, Types.VARCHAR);
log("executeUpdate start: " + lockKey + "] ");
cStmt.executeUpdate();
log("executeUpdate end: " + lockKey + "] ");
rc = cStmt.getInt(2);
log("return value from request=[" + rc + "] ");
if (rc != 0) {
System.out.println("6001 lock obtained: "
+ Thread.currentThread().getName());
throw new RuntimeException("lock acquisition failed with code=" + rc);
}
log("v_lockhandle=[" + cStmt.getString(4) + "] ");
for (int i = 0; i < 4; i++) {
try {
Thread.sleep(1000 * 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log("***** protected code iteration ***** " + i);
}
con.commit();
} catch (SQLException e) {
log("int timeout: " + Thread.currentThread().getName());
throw new RuntimeException("SQLException locking balance for user "
+ key, e);
} finally {
try {
if (cStmt != null) {
cStmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
log("Exiting=[" + rc + "] ");
}
public static void main(String[] args) throws Exception {
new oracle.jdbc.OracleDriver();
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 2; i++) {
Connection connection = DriverManager
.getConnection("jdbc:oracle:thin:#localhost:1521:xe",
"<username>", "password");
Thread t = new Thread(new DbmsLockTest(connection, "mykey", 10));
list.add(t);
}
for (Thread t : list) {
t.start();
}
}
}

SCP from remote host using groovy

I am trying to SCP from a remote host using JSch. I have successfully copied file form remote host in java STS IDE. However, when I tried to run it in groovy script which I am executing using SOAP UI, I get following error.
Fri Jun 07 16:53:02 IST 2013:INFO:Exception : groovy.lang.MissingMethodException: No signature of method: java.lang.Byte.minus() is applicable for argument types: (java.lang.String) values: [0]
Possible solutions: minus(java.lang.Number), minus(java.lang.Character), plus(java.lang.String), plus(java.lang.Character), plus(java.lang.Number), times(groovy.lang.Closure)
My code is:
import com.jcraft.jsch.*;
import java.io.*;
import java.lang.*;
FileOutputStream fos=null;
try{
String user="soapui";
String host="192.168.1.1";
String rfile="//bin//output.txt";
String lfile="E://temp1.txt";
String prefix=null;
if(new File(lfile).isDirectory()){
prefix=lfile+File.separator;
}
JSch jsch=new JSch();
Session session=jsch.getSession(user, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
// exec 'scp -f rfile' remotely
String command="scp -f "+rfile;
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
// get I/O streams for remote scp
OutputStream out=channel.getOutputStream();
InputStream ins=channel.getInputStream();
channel.connect();
byte[] buf=new byte[10240];
// send '\0'
buf[0]=0; out.write(buf, 0, 1); out.flush();
while(true){
int c=checkAck(ins);
if(c!='C'){
break;
}
// read '0644 '
ins.read(buf, 0, 5);
long filesize=0L;
while(true){
if(ins.read(buf, 0, 1)<0){
// error
break;
}
if(buf[0]==' ')break;
//char c1='0';
//long tmp=Long.valueOf(buf[0]-'0');
**filesize=filesize*10L+(long)(buf[0]-'0');**
}
String file=null;
for(int i=0;;i++){
ins.read(buf, i, 1);
if(buf[i]==(byte)0x0a){
file=new String(buf, 0, i);
break;
}
}
log.info("filesize="+filesize+", file="+file);
// send '\0'
buf[0]=0; out.write(buf, 0, 1); out.flush();
// read a content of lfile
fos=new FileOutputStream(prefix==null ? lfile : prefix+file);
int foo;
while(true){
if(buf.length<filesize) foo=buf.length;
else foo=(int)filesize;
foo=ins.read(buf, 0, foo);
if(foo<0){
// error
break;
}
fos.write(buf, 0, foo);
filesize-=foo;
if(filesize==0L) break;
}
fos.close();
fos=null;
log.info("Closing Stream");
if(checkAck(ins)!=0){
System.exit(0);
}
// send '\0'
buf[0]=0; out.write(buf, 0, 1); out.flush();
}
session.disconnect();
System.exit(0);
}
catch(Exception e){
log.info("Exception : " + e);
try{if(fos!=null)fos.close();}catch(Exception ee){}
}
static int checkAck(InputStream ins) throws IOException{
int b=ins.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if(b==0) return b;
if(b==-1) return b;
if(b==1 || b==2){
StringBuffer sb=new StringBuffer();
int c;
while(c!='\n') {
c=ins.read();
sb.append((char)c);
}
if(b==1){ // error
System.out.print(sb.toString());
}
if(b==2){ // fatal error
System.out.print(sb.toString());
}
}
return b;
}
public class MyUserInfo implements UserInfo{
public String getPassword(){ return passwd;}
public boolean promptYesNo(String str){return true;}
String passwd="123";
public String getPassphrase(){return null;}
public boolean promptPassphrase(String message){return true;}
public boolean promptPassword(String message){return true;}
public void showMessage(String s){};
}
What I have debugged is that on line filesize=filesize*10L+(long)(buf[0]-'0'); of code, groovy fails and generates the exception groovy.lang.MissingMethodException: No signature of method: java.lang.Byte.minus(). Please suggest some solution to this issue.
In groovy, '0' is a String constant, not a char or byte. You can't subtract a String from a byte. Convert it to a char or use the first byte:
byte b = 51 // ASCII '3'
assert b - ('0' as char) == 3
assert b - '0'.bytes[0] == 3
A better way to get a digit from a byte is to use Character.digit(). For example:
filesize = filesize * 10L + Character.digit(buf[0], 10)

java.lang.nullpointerexception in j2me

I am writing an application for read the mifare card,but when I pass the APDU the error occur that on emulator "java.lang.nullpointerexception".I have successfully detect the ISO14443_CARD after that I pass the APDU like
if (tp.hasTargetType(TargetType.ISO14443_CARD)){
form.append("Target is ISO14443_CARD\n");
try {
static byte[] APDU_AUTH1 = { (byte) 0xff, (byte) 0x86, (byte) 0x00, (byte) 0x00, (byte) 0x05,(byte)0x01,(byte)0x00,(byte)0xfc,(byte)0x60,(byte)0x00};
static byte[] STATUS_BYTE = {(byte)0x90,(byte)0x00};
if(STATUS_BYTE == iso14443.exchangeData(APDU_LOAD_KEY))
{
String value1 = new String("Hai!");
textfield1.setString(value1);
form.append(textfield1);
}
else
{
String value1 = new String("Hello!");
textfield1.setString(value1);
form.append(textfield1);
}
}
catch (Exception ex) {
form.append(ex.toString());
}
}
Either of iso14443 or textfield1 objects is likely null.
With the way you debug things (quite smart BTW, my congratulations), you could log the checks about as follows:
form.append("\n\n iso14443 is null: [" + (iso14443 == null)
+ "],\n textfield1 is null: [" + (textfield1 == null) + "]");

Resources