i have some problem with my linq database with a one to many relation. Here are classes:
private EntityRef<Account> _account;
[Association(Storage = "_account", ThisKey = "IDMovement", OtherKey = "IDAccount", IsForeignKey = true)]
public Account Account
{
get { return this._account.Entity; }
set
{
Account previousValue = this._account.Entity;
if (((previousValue != value) || (this._account.HasLoadedOrAssignedValue == false)))
{
NotifyPropertyChanging("Account");
if ((previousValue != null))
{
this._account.Entity = null;
previousValue.Movements.Remove(this);
}
this._account.Entity = value;
if ((value != null))
{
value.Movements.Add(this);
}
NotifyPropertyChanged("Account");
}
}
}
and on the other side:
private EntitySet<Movement> _movements;
[Association(Storage = "_movements", OtherKey = "IDMovement", ThisKey = "IDAccount")]
public EntitySet<Movement> Movements
{
get { return this._movements; }
set { this._movements.Assign(value); }
}
private void OnMovementAdded(Movement movement)
{
NotifyPropertyChanging("Movement");
movement.Account = this;
NotifyPropertyChanged("Movement");
}
private void OnMovementRemoved(Movement movement)
{
NotifyPropertyChanging("Movement");
movement.Account = null;
NotifyPropertyChanged("Movement");
}
my problem is that when i have to insert new movements in the database i don't know how to assign the "EntityRef _account" variable with a value that i already have in the database.
For example: i have to insert a movement for the account "general", this account is already in my database of course...how can i say to my movement that the account "general" that it has in "movement.Account" it's exactly the same included in my database?
I tried something like that but It doesn't work because it's like i have created a new account:
Movement movement = new Movement();
movement.Category = (from f in context.Categories
where f.Name == this.Categories.ElementAt(this.ChoosenCategory).Name
select f).FirstOrDefault();
movement.Account = (from f in context.Accounts
where f.Name == ChoosenAccount.Name
select f).FirstOrDefault();
context.Movements.InsertOnSubmit(movement);
context.SubmitChanges();
You need to call Load() method for EntityRef such as if (!order.CustomersReference.IsLoaded)
order.CustomersReference.Load();
Related
Looking for some validation on the approach to using ANTLR 4 to parse SQL joins.
I have generated a lexer, parser and visitor from the following grammar.
https://github.com/antlr/grammars-v4/tree/master/tsql
I can then create a parse tree (in this example for a view) and I can kick off a walk of tree using a listener I have implemented.
ICharStream stream = CharStreams.fromstring(view);
ITokenSource lexer = new TSqlLexer(stream);
ITokenStream tokens = new CommonTokenStream(lexer);
TSqlParser parser = new TSqlParser(tokens);
parser.BuildParseTree = true;
IParseTree tree = parser.create_view();
TSqlListener listener = new TSqlListener();
ParseTreeWalker.Default.Walk(listener, tree);
My question is. Is my method of extracting the tokens for the joins the 'correct' and most efficient way of doing this.
My implementation is below and i based on listening for a walk of the tree at the join conditions. I need to capture table aliases and relate them to columns so I need to be in the same context when I'm walking the tree. Hence I'm manually descending in a single method.
public void EnterTable_sources([NotNull] TSqlParser.Table_sourcesContext context)
{
var table_sources = context.table_source().ToList();
foreach (var table_source in table_sources)
{
var item = table_source.table_source_item_joined();
if (item != null)
{
//first aliases
var source_item = item.table_source_item();
if (source_item != null)
{
TableAlias tableAlias = new TableAlias();
var table_name = source_item.table_name_with_hint();
if (table_name != null)
{
var fullTableName = table_name.GetText();
if (fullTableName.Contains('.'))
{
var nameParts = fullTableName.Split('.').ToList();
for (int i = 0; i <nameParts.Count; i++)
{
tableAlias.AddParts(nameParts);
}
}
else
{
tableAlias.AddParts(fullTableName);
}
}
var table_alias = source_item.as_table_alias();
if (table_alias != null)
{
tableAlias.Alias = table_alias.GetText();
}
JoinAnalysis.Aliases.Add(tableAlias);
}
var join_parts = item.join_part();
foreach (var join_part in join_parts)
{
var table_source_joins = join_part.table_source();
if (table_source_joins != null)
{
//The join table and alias
var table_source_item_joined = table_source_joins.table_source_item_joined();
if (table_source_item_joined != null)
{
var joinAlias = new TableAlias();
var table_source_item = table_source_item_joined.table_source_item();
var table_name = table_source_item.table_name_with_hint();
if (table_name != null)
{
var fullTableName = table_name.GetText();
if (fullTableName.Contains('.'))
{
var nameParts = fullTableName.Split('.').ToList();
joinAlias.AddParts(nameParts);
}
else
{
joinAlias.AddParts(fullTableName);
}
}
if (table_source_item != null)
{
var table_alias = table_source_item.as_table_alias();
if (table_alias != null)
{
joinAlias.Alias = table_alias.GetText();
}
}
if (joinAlias.Alias != null)
{
JoinAnalysis.Aliases.Add(joinAlias);
}
}
}
var search_condition = join_part.search_condition();
if (search_condition != null)
{
//The join conditions
var conditions = search_condition.search_condition_and();
if (conditions != null)
{
foreach (var condition in conditions)
{
if (condition != null)
{
foreach (var search_condition_not in condition.search_condition_not())
{
JoinCondition joinCondition = new JoinCondition();
joinCondition.LineNumber = search_condition_not.Start.Line;
var conditionText = search_condition_not.GetText();
joinCondition.JoinConditionText = conditionText;
var splitCondition = conditionText.Split("=");
if (splitCondition.Length == 2)
{
joinCondition.LeftPart = splitCondition[0];
joinCondition.RightPart = splitCondition[1];
}
JoinAnalysis.JoinConditions.Add(joinCondition);
}
}
}
}
}
}
}
}
}
Is there a better way to do this using all of the other listener methods that have been generated without manually descending into child nodes? I there some magic that I'm missing that holds context between nodes as they are walked?
Instead of manually drilling down to sub elements in a rule you can simply listen to the the enter/exit calls for these subrules. As an example: you listen to table_sources and descent to table_source_item_joined from there to table_name_with_hint. Instead you could simply override the EnterTable_name_with_hint method.
It is totally ok to write a listener, which only handles very specific parts of the language. Look at this (C++) code in MySQL Workbench, where I created several listeners, each just handling a subpart of a larger construct or individual objects. There are listeners for create table, alter table, column definitions, triggers and more.
In case of Directory Entry, one can connect and find the NetBios Domain name as follows :-
private string GetNetbiosDomainName(string dnsDomainName)
{
string netbiosDomainName = string.Empty;
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
string configurationNamingContext = rootDSE.Properties["configurationNamingContext"][0].ToString();
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=Partitions," + configurationNamingContext);
DirectorySearcher searcher = new DirectorySearcher(searchRoot);
//searcher.SearchScope = SearchScope.OneLevel;
searcher.PropertiesToLoad.Add("netbiosname");
searcher.Filter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", dnsDomainName);
SearchResult result = searcher.FindOne();
if (result != null)
{
netbiosDomainName = result.Properties["netbiosname"][0].ToString();
}
return netbiosDomainName;
}
where dnsDomainName is a Fully qualified Domain name .
However, in case of System.DirectoryServices.Protocols , How can one connect and find such NetBios Domain name when fully qualified domain name is given ?
Here is the solution i have got in one research paper:-
private string GetDomainNetBios(string sDomainFqdn,NetworkCredential netCred)
{
string sNetBios=string.Empty;
LdapDirectoryIdentifier oLdapDirectory = null;
LdapConnection oLdapConnection = null;
try
{
oLdapDirectory = new LdapDirectoryIdentifier(sDomainFqdn, 389);
oLdapConnection = (netCred == null)
? new LdapConnection(oLdapDirectory)
: new LdapConnection(oLdapDirectory, netCred);
oLdapConnection.Timeout = TimeSpan.FromSeconds(45);
oLdapConnection.SessionOptions.TcpKeepAlive = true;
oLdapConnection.SessionOptions.ProtocolVersion = 3;
//prevents ldap connection from connecting to other servers during session
oLdapConnection.SessionOptions.ReferralChasing = ReferralChasingOptions.None;
oLdapConnection.AutoBind = false;
oLdapConnection.Bind();
SearchResponse dirRes = (SearchResponse)_ldapConnectionUsers.SendRequest(new
SearchRequest(
null,
"configurationNamingContext=*",
SearchScope.Base,
"configurationNamingContext"
));
if (dirRes != null)
{
string sConfPartDn =
dirRes.Entries[0].Attributes["configurationNamingContext"][0].ToString();
dirRes = (SearchResponse)_ldapConnectionUsers.SendRequest(new SearchRequest(
sConfPartDn,
String.Format(CultureInfo.InvariantCulture,"(&(nETBIOSName=*)(dnsRoot={0}))", sDomainFqdn),
SearchScope.Subtree,
"nETBIOSName"
));
}
if (dirRes != null && dirRes.Entries.Count > 0)
{
sNetBios = dirRes.Entries[0].Attributes["nETBIOSName"][0].ToString();
}
return sNetBios;
}
catch (Exception ex)
{
throw new Exception(string.Format(CultureInfo.InvariantCulture,"{0}::{1}", new StackFrame(0,
true).GetMethod().Name, PvssMgrException.ToString(ex)));
}
finally
{
oLdapConnection.Dispose();
}
}
I am new to Google Drive and have following scenarios for which I am not able to find anything (not sure if anything exists or not)
–> I am creating a Windows app which will be SAAS based. Different Users will register and create their company logins and subusers under them. Now I want them to put the google drive credentials in one of the form and this should work for rest of the users. Currently the problem is that while development I got the google log in done and it never asks for the login again but when testing on a different system with different login, it keeps asking for google login. I simply want admin users to put their google drive credentials and it should work for upload and download files for all the users for that company.
–> I want to keep versions of the same file (just like google drive does by default) on google drive. Lets say user A uploaded file xyz and then user B downloaded and changed file xyz and uploaded it on the drive again.
I want 2 things here – only the changed content should get uploaded and not the whole file (this will save time for the user)
2ndly I want to have history of the same file so I can show in my Windows application
#region Get Service Object
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "GoogleDriveClientID",
ClientSecret = "GoogleDriveClientSecret"
},
new[] { DriveService.Scope.Drive }, "user", CancellationToken.None).Result;
// Create the service.
service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "AppName",
});
#endregion
#region Uploading
public void uploadOnGoogleDrive(ObservableCollection<JobAttachments> AttachmentsColl, bool IsDocSaved)
{
try
{
service = getServiceObject();
List<Google.Apis.Drive.v2.Data.File> fileList = retrieveAllFiles(service);
List<Google.Apis.Drive.v2.Data.File> directoryList = GetDirectoryList(service);
if (IsDocSaved)
{
#region for checking if the file already exists
foreach (Google.Apis.Drive.v2.Data.File item in fileList)
{
foreach (JobAttachments attach in AttachmentsColl)
{
if (item.Title == attach.AttachmtGUID)
{
MessageBoxResult result = System.Windows.MessageBox.Show(LogMessages.GetResourceMessage(LogMessages.MessageEnumeration.GD_AlreadyExistsMsg), "Confirmation", MessageBoxButton.YesNoCancel);
if (result == MessageBoxResult.Yes)
{
//DeleteFile(service, item);
Google.Apis.Drive.v2.Data.File body = new Google.Apis.Drive.v2.Data.File();
body.Title = attach.AttachmtGUID;
body.MimeType = item.MimeType;
fileSize = body.FileSize;
byte[] byteArray = System.IO.File.ReadAllBytes(attach.AttachmentName);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
FilesResource.UpdateMediaUpload request = service.Files.Update(body, item.Id, stream, item.MimeType);
request.Upload();
}
else
{
return;
}
break;
}
}
}
#endregion
}
else
{
#region for direct uploading on google drive
if (AttachmentsCollection != null && AttachmentsCollection.Count > 0)
{
string folderID = string.Empty;
if (_IsProject)
{
if (directoryList != null && directoryList.Count > 0)
{
foreach (var dir in directoryList)
{
if (dir.Title.Equals(_ProjectName))
{
folderID = dir.Id;
break;
}
}
}
if (string.IsNullOrEmpty(folderID))
{
Google.Apis.Drive.v2.Data.File foldbody = new Google.Apis.Drive.v2.Data.File();
foldbody.Title = _ProjectName;
foldbody.MimeType = "application/vnd.google-apps.folder";
foldbody.Parents = new List<ParentReference>() { new ParentReference() { Id = "root" } };
Google.Apis.Drive.v2.Data.File file = service.Files.Insert(foldbody).Execute();
folderID = file.Id;
}
}
else
{
//project folder
string prjFolder = string.Empty;
string tskFolder = string.Empty;
Google.Apis.Drive.v2.Data.File foldbody;
if (directoryList != null && directoryList.Count > 0)
{
foreach (var dir in directoryList)
{
if (dir.Title.Equals(_ProjectName))
{
prjFolder = dir.Id;
break;
}
}
}
if (string.IsNullOrEmpty(prjFolder))
{
foldbody = new Google.Apis.Drive.v2.Data.File();
foldbody.Title = _ProjectName;
foldbody.MimeType = "application/vnd.google-apps.folder";
foldbody.Parents = new List<ParentReference>() { new ParentReference() { Id = "root" } };
Google.Apis.Drive.v2.Data.File file = service.Files.Insert(foldbody).Execute();
prjFolder = file.Id;
}
//task folder
if (directoryList != null && directoryList.Count > 0)
{
foreach (var dir in directoryList)
{
if (dir.Title.Equals(_TaskName) && dir.Parents[0].Id.Equals(prjFolder))
{
folderID = dir.Id;
break;
}
}
}
if (string.IsNullOrWhiteSpace(folderID))
{
foldbody = new Google.Apis.Drive.v2.Data.File();
foldbody.Title = _TaskName;
foldbody.MimeType = "application/vnd.google-apps.folder";
foldbody.Parents = new List<ParentReference>() { new ParentReference() { Id = prjFolder } };
Google.Apis.Drive.v2.Data.File file1 = service.Files.Insert(foldbody).Execute();
folderID = file1.Id;
}
}
foreach (JobAttachments item in AttachmentsColl)
{
if (!string.IsNullOrEmpty(item.AttachmentName))
{
Google.Apis.Drive.v2.Data.File body = new Google.Apis.Drive.v2.Data.File();
body.Title = item.AttachmtGUID;
body.MimeType = item.MimeType;
body.Parents = new List<ParentReference>() { new ParentReference() { Id = folderID } };
//fileSize = body.FileSize;
byte[] byteArray = System.IO.File.ReadAllBytes(item.AttachmentName);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, item.MimeType);
request.Upload();
}
}
}
#endregion
}
}
catch (Exception ex)
{
if (ex.InnerException != null)
throw ex.InnerException;
}
}
#endregion
#region Download File
private async Task DownloadFile(DriveService service, string url, string title, long? fSize)
{
service = getServiceObject();
var downloader = new MediaDownloader(service);
//downloader.ChunkSize = 256 * 1024;
downloader.ProgressChanged += Download_ProgressChanged;
var fileName = string.Empty;
//for downloading on system
var SaveFileDialog = new SaveFileDialog();
SaveFileDialog.Title = "Save As";
SaveFileDialog.FileName = title;
Nullable<bool> result = SaveFileDialog.ShowDialog();
if (result == true)
fileName = SaveFileDialog.FileName;
else if (result == false)
{
prgrsBar.StyleSettings = new ProgressBarStyleSettings();
prgrsBar.Value = 0;
return;
}
else
{
if (Directory.Exists(#"\Downloads"))
fileName = #"\Downloads\" + title;
}
if (!string.IsNullOrWhiteSpace(fileName))
using (var fileStream = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
fileSize = fSize;
var progress = await downloader.DownloadAsync(url, fileStream);
if (progress.Status.ToString() == DownloadStatus.Completed.ToString())
{
fName = fileStream.Name;
prgrsBar.StyleSettings = new ProgressBarStyleSettings();
prgrsBar.Value = 0;
fileStream.Flush();
}
if (progress.Status.ToString() == DownloadStatus.Failed.ToString())
{
HandleDocuments.IsEditButtonClicked = false;
MessageBox.Show("Failed......." + progress.Exception.Message);
}
}
}
#endregion
#region Delete File
private Task DeleteFile(DriveService service, Google.Apis.Drive.v2.Data.File file)
{
service = getServiceObject(); //comment this if calling from another function; create the service object in that function and pass it as parameter to this function.
service.Files.Delete(file.Id).ExecuteAsync();
service.Files.EmptyTrash();
return null;
}
#endregion
#region Get all Directories and Files from Google Drive
public List<Google.Apis.Drive.v2.Data.File> GetDirectoryList(DriveService service)
{
//Creating the global list
List<Google.Apis.Drive.v2.Data.File> AllDirectories = new List<Google.Apis.Drive.v2.Data.File>();
//setting up the Request.
FilesResource.ListRequest request = service.Files.List();
//MaxResults: How many we want back at a time max is 1000
request.MaxResults = 1000;
//Q: Search results. all i want are folders that havent been trashed (deleted)
request.Q = "mimeType='application/vnd.google-apps.folder' and trashed=false";
do
{
try
{
// getting the results
FileList files = request.Execute();
// adding the results to the list.
AllDirectories.AddRange(files.Items);
// If there are more results then your MaxResults you will have a nextPageToken to get the rest of the results.
request.PageToken = files.NextPageToken;
}
catch (Exception ex)
{
request.PageToken = null;
if (ex.InnerException != null)
throw ex.InnerException;
}
} while (!String.IsNullOrEmpty(request.PageToken));
List<Google.Apis.Drive.v2.Data.File> DirsInRoot = AllDirectories.Where(a => (a.Parents.Count > 0 && a.Parents.FirstOrDefault().IsRoot.HasValue) ? a.Parents.FirstOrDefault().IsRoot.Value : false).ToList<Google.Apis.Drive.v2.Data.File>();
List<string> HirearcyList = new List<string>();
// The first Dir is Root it doesnt get returned. But we need it if we
// Want to be able to list the files that are in the root dir.
HirearcyList.Add("Root");
// recersive magic here.
foreach (Google.Apis.Drive.v2.Data.File myDir in DirsInRoot)
{
HirearcyList.Add(" " + myDir.Title);
HirearcyList.AddRange(RecsiveDir(AllDirectories, myDir.Id, " "));
}
return AllDirectories;
}
public List<String> RecsiveDir(List<Google.Apis.Drive.v2.Data.File> allDirs, string ParentId, string Prefix)
{
List<string> result = new List<string>();
List<Google.Apis.Drive.v2.Data.File> DirsInParentId = allDirs.Where(a => (a.Parents.Count > 0 && a.Parents.FirstOrDefault().IsRoot.HasValue) ? a.Parents.FirstOrDefault().Id == ParentId : false).ToList<Google.Apis.Drive.v2.Data.File>();
foreach (Google.Apis.Drive.v2.Data.File myDir in DirsInParentId)
{
result.Add(Prefix + myDir.Title);
result.AddRange(RecsiveDir(allDirs, myDir.Id, Prefix + " "));
}
return result;
}
public static List<Google.Apis.Drive.v2.Data.File> retrieveAllFiles(DriveService service)
{
List<Google.Apis.Drive.v2.Data.File> result = new List<Google.Apis.Drive.v2.Data.File>();
FilesResource.ListRequest request = service.Files.List();
request.MaxResults = 1000;
do
{
try
{
FileList files = request.Execute();
result.AddRange(files.Items);
request.PageToken = files.NextPageToken;
//service.Revisions.List(files.Items[0].Id) // for getting the file Revision history
}
catch (Exception ex)
{
request.PageToken = null;
if (ex.InnerException != null)
throw ex.InnerException;
}
} while (!String.IsNullOrEmpty(request.PageToken));
return result;
}
#endregion
Thanks
Jatinder
I am creating a WPF application to create digital catalog using kinect v1.8. I am trying to track only a single skeleton using following code:-
private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameReadyEventArgs)
{
// Even though we un-register all our event handlers when the sensor
// changes, there may still be an event for the old sensor in the queue
// due to the way the KinectSensor delivers events. So check again here.
if (this.KinectSensor != sender)
{
return;
}
SkeletonFrame skeletonFrame = skeletonFrameReadyEventArgs.OpenSkeletonFrame();
if (skeletonFrame == null)
return;
Skeleton[] skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
Skeleton skeleton = (from skl in skeletons
where skl.TrackingState == SkeletonTrackingState.Tracked
select skl).FirstOrDefault();
if (skeleton == null)
return;
Skeleton[] s = new Skeleton[1];
s[0] = skeleton;
if (SkeletonTrackingState.Tracked == s[0].TrackingState)
{
//s1.SkeletonStream.ChooseSkeletons(s[0].TrackingId);
var accelerometerReading = this.KinectSensor.AccelerometerGetCurrentReading();
this.interactionStream.ProcessSkeleton(s, accelerometerReading, skeletonFrame.Timestamp);
}
}
I am getting an exception when I run the code and skeleton gets detected as follows:-
on the line "this.interactionStream.ProcessSkeleton(s, accelerometerReading, skeletonFrame.Timestamp);"
I need to detect only one skeleton and use it for further processing like to access the digital catalog applications.
Thanks in advance.
I have Faced Same Problem By using below code I have track only one skeleton Which is closer to the sensor.and directly assign the closest skeleton to the main skeleton stream.
private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameReadyEventArgs)
{
Skeleton[] skeletons = new Skeleton[0];
using (SkeletonFrame skeletonFrame = skeletonFrameReadyEventArgs.OpenSkeletonFrame())
{
if (skeletonFrame != null && this.skeletons != null)
{
//Console.WriteLine(skeletonFrame.SkeletonArrayLength);
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
// Set skeleton datas from skeletonFrame
skeletonFrame.CopySkeletonDataTo(this.skeletons);
TrackClosestSkeleton();
Skeleton[] singleSkeleton = new Skeleton[6];
Skeleton skl=(from mno in this.skeletons where mno.TrackingState==SkeletonTrackingState.Tracked && mno.TrackingId==globalClosestID select mno).FirstOrDefault();
if (skl == null)
return;
//Creating an empty skkeleton
Skeleton emptySkeleton = new Skeleton();
singleSkeleton[0] = skl; //Pass the Tracked skeleton with closestID
singleSkeleton[1] = emptySkeleton; //Passing Empty Skeleton
singleSkeleton[2] = emptySkeleton; //Passing Empty Skeleton
singleSkeleton[3] = emptySkeleton; //Passing Empty Skeleton
singleSkeleton[4] = emptySkeleton; //Passing Empty Skeleton
singleSkeleton[5] = emptySkeleton; //Passing Empty Skeleton
this.snew.SkeletonStream.ChooseSkeletons(globalClosestID);
var accelerometerReading = this.KinectSensor.AccelerometerGetCurrentReading();
this.interactionStream.ProcessSkeleton(singleSkeleton, accelerometerReading, skeletonFrame.Timestamp);
}
}
}
int globalClosestID = 0;
private void TrackClosestSkeleton()
{
if (this.snew != null && this.snew.SkeletonStream != null)
{
if (!this.snew.SkeletonStream.AppChoosesSkeletons)
{
this.snew.SkeletonStream.AppChoosesSkeletons = true; // Ensure AppChoosesSkeletons is set
}
float closestDistance = 10000f; // Start with a far enough distance
int closestID = 0;
foreach (Skeleton skeleton in this.skeletons.Where(s => s.TrackingState != SkeletonTrackingState.NotTracked))
{
if (skeleton.Position.Z < closestDistance)
{
closestID = skeleton.TrackingId;
closestDistance = skeleton.Position.Z;
}
}
if (closestID > 0)
{
this.snew.SkeletonStream.ChooseSkeletons(closestID); // Track this skeleton
globalClosestID = closestID;
}
}
}
check the above code it works for me.It may helpful to you.Here snew is the Kinectsensor.
You should try to track the closest skeleton using this method from MSDN
private void TrackClosestSkeleton()
{
if (this.kinect != null && this.kinect.SkeletonStream != null)
{
if (!this.kinect.SkeletonStream.AppChoosesSkeletons)
{
this.kinect.SkeletonStream.AppChoosesSkeletons = true; // Ensure AppChoosesSkeletons is set
}
float closestDistance = 10000f; // Start with a far enough distance
int closestID = 0;
foreach (Skeleton skeleton in this.skeletonData.Where(s => s.TrackingState != SkeletonTrackingState.NotTracked))
{
if (skeleton.Position.Z < closestDistance)
{
closestID = skeleton.TrackingId;
closestDistance = skeleton.Position.Z;
}
}
if (closestID > 0)
{
this.kinect.SkeletonStream.ChooseSkeletons(closestID); // Track this skeleton
}
}
}
And then in your SkeletonFrameReady
private void SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
Skeleton[] skeletons = new Skeleton[0];
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null && this.skeletonData != null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
// Set skeleton datas from skeletonFrame
skeletonFrame.CopySkeletonDataTo(this.skeletonData);
TrackClosestSkeleton();
}
}
//Do some stuff here
}
In GAE, I've got a table full of "one offs" -- things like "last-used sequence number" and the like that don't really fall into other tables. It's a simple String-key with String-value pair.
I've got some code to grab a named integer and increment it, like so:
#PersistenceCapable(detachable="true")
public class OneOff
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String dataKey;
#Persistent
private String value;
public OneOff(String kk, String vv)
{
this.dataKey = kk;
this.value = vv;
}
public static OneOff persistOneOff(String kk, String vv)
{
OneOff oneoff= new OneOff(kk, vv);
PersistenceManager pm = PMF.get().getPersistenceManager();
try
{
pm.makePersistent(oneoff);
}
finally
{
pm.close();
}
return oneoff;
}
// snip...
#SuppressWarnings("unchecked")
synchronized
public static int getIntValueForKeyAndIncrement(String kk, int deFltValue)
{
int result = 0;
OneOff oneOff = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(OneOff.class);
query.setFilter("dataKey == kkParam");
query.declareParameters("String kkParam");
List<OneOff> oneOffs = (List<OneOff>) query.execute(kk);
int count = oneOffs.size();
if (count == 1)
{
oneOff = oneOffs.get(0);
result = Integer.parseInt(oneOff.value);
}
else if (count == 0)
{
oneOff = new OneOff(kk, "default");
result = deFltValue;
}
else
{
// Log WTF error.
}
// update object in DB.
oneOff.value = "" + (result+1);
try
{
pm.makePersistent(oneOff);
}
finally
{
pm.close();
}
return result;
}
// etc...
However, when I make these calls:
int val1 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val2 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val3 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
Sometimes I get the desired increment and sometimes I get the same value. It appears that my DB access is running asynchronously, when I'd like to lock the DB for this particular transaction.
I thought that
synchronized
public static
was supposed to do that for me, but apparently not (probably due to multiple instances running!)
At any rate -- how do I do the thing that I want? (I want to lock my DB while I get & update this value, to make the whole thing concurrency-safe.)
Thanks!
== EDIT ==
I have accepted Robert's as the correct answer, since transactions were, indeed, what I wanted. However, for completeness, I have added my updated code below. I think it's correct, although I'm not sure about the if(oneOff==null) clause (the try-catch bit.)
public static int getIntValueForKeyAndIncrement(String kk, int defltValue)
{
int result = 0;
Entity oneOff = null;
int retries = 3;
// Using Datastore Transactions
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
while (true)
{
com.google.appengine.api.datastore.Transaction txn = datastore.beginTransaction();
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = datastore.get (oneOffKey);
result = Integer.parseInt((String) oneOff.getProperty("value"));
oneOff.setProperty("value", "" + (result+1));
datastore.put(oneOff);
txn.commit();
break;
}
catch (EntityNotFoundException ex)
{
result = defltValue;
}
catch (ConcurrentModificationException ex)
{
if (--retries < 0)
{
throw ex;
}
}
if (oneOff == null)
{
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = new Entity(oneOffKey);
oneOff.setProperty("value", "" + (defltValue+1));
datastore.put(txn, oneOff);
datastore.put(oneOff);
txn.commit();
break;
}
finally
{
if (txn.isActive())
{
txn.rollback();
}
}
}
else
{
if (txn.isActive())
{
txn.rollback();
}
}
}
return result;
}
You should be updating your values inside a transaction. App Engine's transactions will prevent two updates from overwriting each other as long as your read and write are within a single transaction. Be sure to pay attention to the discussion about entity groups.