TFS API - How to obtain the parent of a work item - c#

My ultimate goal is to get the parent of one work item at a time recursively, until there are no more parents in the hierarchy. At the moment, there is nothing recursive yet, I am still at the point of optimizing the way I obtain the parent work item. I have thought of a way of doing this involving a query:
public WorkItem GetParentWorkItem(int id)
{
StringBuilder queryString = new StringBuilder("SELECT [System.Id]" +
" FROM WorkItemLinks " +
" WHERE [Source].[System.WorkItemType] = '" + TFS_TIMESHEET_WORK_ITEM_TYPE + "'" +
" AND [Source].[System.TeamProject] = '" + TFS_TIMESHEET_PROJECT_KEY + "'" +
" AND [Source].[System.Id] = " + id
);
Query wiQuery = new Query(GetWorkItemStore, queryString.ToString());
WorkItemLinkInfo[] wiTrees = wiQuery.RunLinkQuery();
WorkItem wi = GetWorkItemStore.GetWorkItem(wiTrees[1].TargetId);
return wi;
}
The problem with this method is that it gets all the linked work items, including predecessor, successor, child and parents. I knew that wiTrees[1] was the parent work item so I hard coded the index.
I found out a way to get the "parent" WorkItemTypeEnd object from the work item store:
WorkItemLinkTypeEnd linkTypEnd = GetWorkItemStore.WorkItemLinkTypes.LinkTypeEnds["Parent"];
Where do I go from here?

This works on TFS 2013:
var parent_link = work_item.WorkItemLinks.Cast<WorkItemLink> ().FirstOrDefault (x => x.LinkTypeEnd.Name == "Parent");
WorkItem parent_work_item = null;
if (parent_link != null)
parent_work_item = work_item_store.GetWorkItem (parent_link.TargetId);

Found a solution, which returns the parent WorkItem if there is a parent, if not returns null.
public WorkItem GetParentWorkItem(int id)
{
StringBuilder queryString = new StringBuilder("SELECT [System.Id]" +
" FROM WorkItemLinks " +
" WHERE [Source].[System.WorkItemType] = '" + TFS_TIMESHEET_WORK_ITEM_TYPE + "'" +
" AND [Source].[System.TeamProject] = '" + TFS_TIMESHEET_PROJECT_KEY + "'" +
" AND [Source].[System.Id] = " + id
);
Query wiQuery = new Query(GetWorkItemStore, queryString.ToString());
WorkItemLinkInfo[] wiTrees = wiQuery.RunLinkQuery();
int parentLinkId = GetWorkItemStore.WorkItemLinkTypes.LinkTypeEnds["Parent"].Id;
foreach (WorkItemLinkInfo linkInfo in wiTrees)
{
// -2 is the LinkTypeId for parent
if (linkInfo.LinkTypeId == parentLinkId)
{
workItem = GetWorkItemStore.GetWorkItem(linkInfo.TargetId);
break;
}
else
{
workItem = null;
}
}
return workItem;
}

Related

Increase the amount of data on listview when the data is successfully stored in sqlite in uwp

I have a listview whose data comes from a sqlite database. The database is created when the user selects the list on the previous page whose data comes from JSON.
Code:
ConnectionProfile connections = NetworkInformation.GetInternetConnectionProfile();
if (connections != null && connections.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess)
{
loading.IsIndeterminate = true;
try
{
string urlPath = "https://.../tryout_perid";
var httpClient = new HttpClient(new HttpClientHandler());
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("tid", ((App)(App.Current)).ID)
};
var response = await httpClient.PostAsync(urlPath, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
if (!response.IsSuccessStatusCode)
{
loading.IsIndeterminate = false;
RequestException();
}
string jsonText = await response.Content.ReadAsStringAsync();
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonArray jsonData = jsonObject["data"].GetArray();
foreach (JsonValue groupValue1 in jsonData)
{
JsonObject groupObject2 = groupValue1.GetObject();
string id = groupObject2["id"].GetString();
string title = groupObject2["judul"].GetString();
QuizHome quiz = new QuizHome();
quiz.ID = id;
((App)(App.Current)).ID = quiz.ID.ToString();
quiz.Title = title;
quizDataSource.Add(quiz);
if (quizDataSource.Count > 0)
{
string InsertQuiz = #"INSERT INTO DBName (ID,Judul) SELECT '" + id.ToString() + "','" + title.ToString() + "','" + "' WHERE not exists " +
"(select ID and Judul FROM DBName WHERE ID='" + id.ToString() + "' and Judul='" + title.ToString() + "')";
var quizName = objConn.Prepare(InsertQuiz);
quizName.Step();
}
JsonArray jsonDataSoal = groupObject2["list_soal"].GetArray();
foreach (JsonValue groupValueSoal in jsonDataSoal)
{
JsonObject groupObjectSoal = groupValueSoal.GetObject();
string qid = groupObjectSoal["qid"].GetString();
string pertanyaan = groupObjectSoal["question"].GetString();
QuizQuestion question = new QuizQuestion();
question.QID = qid;
question.Pertanyaan = pertanyaan;
questionDataSource.Add(question);
if (questionDataSource.Count > 0)
{
string InsertQuestion = #"INSERT INTO DBQuestion (QID,Pertanyaan) SELECT '" + qid.ToString() + "','" + pertanyaan.ToString() + "' WHERE not exists " +
"(select QID and Pertanyaan FROM DBQuestion WHERE OID='" + qid.ToString() + "' and Pertanyaan='" + pertanyaan.ToString() + "')";
var quizQuestion = objConn.Prepare(InsertQuestion);
quizQuestion.Step();
}
JsonArray jsonDataOption = groupObjectSoal["jawaban"].GetArray();
foreach (JsonValue groupValueOption in jsonDataOption)
{
JsonObject groupObjectOption = groupValueOption.GetObject();
string oid = groupObjectOption["oid"].GetString();
string option = groupObjectOption["q_option"].GetString();
string score = groupObjectOption["score"].GetString();
QuizOption pilihan = new QuizOption();
pilihan.OID = oid;
pilihan.Option = option;
optionDataSource.Add(pilihan);
if (optionDataSource.Count > 0)
{
string InsertOption = #"INSERT INTO DBOption (OID,Option) SELECT '" + oid.ToString() + "','" + option.ToString() + "','" + "' WHERE not exists " +
"(select OID and Option FROM DBOption WHERE OID='" + oid.ToString() + "' and Option='" + option.ToString() + "')";
var quizOption = objConn.Prepare(InsertOption);
quizOption.Step();
}
}
}
this.Loaded += ReadTryoutList_Loaded;
loading.IsIndeterminate = false;
}
}
private void ReadTryoutList_Loaded(object sender, RoutedEventArgs e)
{
ReadAllDBName dbName = new ReadAllDBName();
DB_TryoutList = dbName.GetAllDBName();
ListTryout.ItemsSource = DB_TryoutList.OrderByDescending(i => i.ID).ToList();//Binding DB data to LISTBOX and Latest contact ID can Display first.
if (DB_TryoutList.Count == 0)
{
statuskosongStack.Visibility = Visibility.Visible;
ListTryout.Visibility = Visibility.Collapsed;
}
else
{
statuskosongStack.Visibility = Visibility.Collapsed;
ListTryout.Visibility = Visibility.Visible;
}
}
I am having problems, that is when the user selects the list on the previous page and the data is successfully stored in the database, but the amount of data on listview is not increased. If I click the back button and enter on this page again, then the data on listview increases. How do I get listview to increase in the number of data when the data is successfully saved?
This issue is caused by the asynchronous method in your code. After you click the item, you navigate to the TryoutLibrary1 page. On this page, you save the data to the database meanwhile you get the data source from the database on the Page.Loaded event. But when you get the data, the clicked item has not been insert into the database, so it will not display on the page until you reload the data(reenter the page again).
So you should reconsider your logic again in the ItemClick event, you should make sure the data have saved into the database then you get and set the data as the ListView.ItemsSource. As a example, when you click the item, you can create a object and put it into a local ObservableCollection object, then set the ObservableCollection as the ListView itemsSource to make it display on the UI, on other side, you save the item to the database.

Nested Linq conversion (select)

Im trying to convert an object (Lead) to a reduced form of the same object (ApiLead)
The object contains a list of objects (OtherInHousehold) which also needs to be reduced (ApiOtherInHousehold):
result = leads.Select(lead => new ApiLead()
{
UserId = lead.UserId,
DepartmentId = lead.DepartmentId,
CompanyId = lead.CompanyId,
CPR_number = lead.CPR_number,
CVR_number = lead.CVR_number,
Name = (lead.FirstName == "[virksomhed]" ? "" : lead.FirstName + " ") + lead.LastName,
Address = (lead.Street + " " + lead.StreetNumber + " " + lead.Floor + " " + lead.Side).Trim(),
Zipcode = lead.Zipcode,
City = (lead.PlaceName + " " + lead.City).Trim(),
Phonenumber = ("Fastnet: " + lead.Phonenumber + " Mobil: " + lead.Cellphonenumber),
Email = lead.Email,
BestReached = lead.BestReached,
**OthersInHousehold = lead.OthersInHousehold.Select(oih => new ApiOtherInHousehold(){ CPR_number = oih.CPR_number, Name = oih.Name }).ToList()**,
WantsVisit = lead.WantsVisit,
WantsPhonecall = lead.WantsPhonecall,
WantsInsuranceImmediately = lead.WantsInsuranceImmediately,
ExistingInsurance = lead.ExistingInsurance,
CurrentInsuranceCompany = lead.CurrentInsuranceCompany,
OtherInfo = lead.OtherInfo,
Status = lead.Status,
CreationDate = lead.CreationDate
}).ToList();
But this throws an
Cannot implicitly convert type 'System.Collections.Generic.List<LeadsApp.ApiModels.ApiLead>' to
'System.Collections.Generic.List<LeadsApp.Models.Lead>'
Is this not possible or am I doing it wrong?
Thanks, guys.
At the linq statement, you are returning List<ApiLead>. But result variable is List<Lead>. You have to declare your result variable as List<ApiLead>.
Hope helps,

c# List inside list XML Linq

I have the following statement
xdoc.Descendants("Father").Select(p => new
{
Son1 = (string)p.Element("Son1").Value,
Son2 = (string)p.Element("Son2").Value,
Son3= (string)p.Element("Son3").Value,
Son4 = (string)p.Element("Son4").Value,
Son5 = (string)p.Element("Son5").Value
}).ToList().ForEach(p =>
{
Response.Write("Son1= " + p.Son1 + " ");
Response.Write("Son2=" + p.Son2 + " ");
Response.Write("Son3=" + p.Son3 + " ");
Response.Write(("Son4 =") + p.Son4 + " ");
Response.Write(("Son5 =") + p.Son5 + " ");
Response.Write("<br />");
});
and it works fine as long as i have only one instance of each son , the problem is that i have multiple instances of Son5, and i don´t know how to put Son5 inside of a list
Here is my XML code Example:
If you have several elements of same type, then you should parse them to list or other collection:
var fathers = from f in xdoc.Descendants("Father")
select new {
Son1 = (string)f.Element("Son1"),
Son2 = (string)f.Element("Son2"),
Son3= (string)f.Element("Son3"),
Son4 = (string)f.Element("Son4"),
Son5 = f.Elements("Son5").Select(s5 => (string)s5).ToList()
};
Some notes:
Don't use .Value of XElement or XAttribute - you can cast element itself to appropriate data type without accessing its value. Benefits - less code, more reliable in case element is missing (you will not get NullReferenceException)
Consider to use int or int? as elemenent values if your elements contain integer values
If you have single Father element, then don't work with collection of fathers. Just get xml root and check whether it's null or not. After that you can create single father object.
Writing response
foreach(var father in fathers)
{
Response.Write($"Son1={father.Son1} ");
Response.Write($"Son2={father.Son2} ");
Response.Write($"Son3={father.Son3} ");
Response.Write($"Son4={father.Son4} ");
Response.Write(String.Join(" ", father.Son5.Select(son5 => $"Son5={son5}"));
Response.Write("<br />");
}
Try this:
xdoc.Descendants("Father").Select(p => new
{
Son1 = p.Element("Son1").Value,
Son2 = p.Element("Son2").Value,
Son3= p.Element("Son3").Value,
Son4 = p.Element("Son4").Value,
Sons5 = p.Elements("Son5").Select(element => element.Value).ToList()
}).ToList().ForEach(p =>
{
Response.Write("Son1= " + p.Son1 + " ");
Response.Write("Son2=" + p.Son2 + " ");
Response.Write("Son3=" + p.Son3 + " ");
Response.Write("Son4 =" + p.Son4 + " ");
p.Sons5.ForEach(son5 => Response.Write("Son5 =" + son5 + " "));
Response.Write("<br />");
});
That will create a list of Son5 within your list of items, which you can iterate in the ForEach with another ForEach.

error: The query results cannot be enumerated more than once

Edit:
DataClassesDataContext dc = new DataClassesDataContext();
string _idCompany = Request["idCompany"];
var newes = dc.GetNewsCompany(Int64.Parse(_idCompany));
string date = "";
string newsHtml = "<center>";
if(newes.GetEnumerator().MoveNext()){
foreach (var item in newes)//say Error .......................
{
// date = calendar.GetDayOfMonth(item.DateSend) + "/" + calendar.GetMonth(item.DateSend) + "/" + calendar.GetYear(item.DateSend).ToString();
// newsHtml += "<li class='news-item'><a style='text-decoration:none' class=\"link\" onclick=\"$(\'#BodyNews\').text(\'" + HttpUtility.HtmlEncode(item.Body).Trim() + "\');$(\'#BodyNews\').dialog({resizable:false});\" href=\"#\" > " + item.Title.ToString() + "</a> " + date + " </li>";
}
newsHtml += "</center>";
}
else
{
// var propertyCompany = dc.GetPropertyCompanyById(Int64.Parse(_idCompany));
// newsHtml += "<li class='news-item'><a style='text-decoration:none' class=\"link\" );$(\'#BodyNews\').dialog({resizable:false});\" href=\"#\" > " + "!به صفحه شخصی شرکت " + propertyCompany.FirstOrDefault().NameCompany + " خوش آمدید " + "</a> " + date + " </li>";
}
return newsHtml;
say error:The query results cannot be enumerated more than once
how check var is empty or null with out enumerated;
Why bother with the if at all?
var newes = dc.GetNewsCompany(Int64.Parse(_idCompany));
//if (newes.GetEnumerator().MoveNext())//check is null or empty
var newesList = newes.ToList();
if (neweList.Count > 0)
{
...
}
You can always check the newesList.Count property afterward.
Not sure what's available as a member in newes, but if it's an object and depending on what dc.GetNewsCompany returns you could check for null
if (news == null) return;
or if it returns an empty collection/array, just check the count/length:
if (news.Count == 0) return;
if (news.Length == 0) return;
the error comes, because you are using .GetEnumerator() on newes and then using the newes again in a foreach Loop .. this causes the "double enumeration".
Generally avoid walking "such var"'s with a foreach, since the DataReader is locked the whole loop !. Means that you cannot use the same entitie in this loop.
Better .ToList() , you can the list.AsQuearable agian if you want to Linq on it
f.e. something like
var newes = dc.CompanyTable.Where(ln => ln.id.Equals(_idCompany));;
List<CompanyTable> newesList = newes.ToList();

client.get("me/statuses") returns empty "data" array using C# Facebook SDK 5.0.3

Using the C# Facebook SDK 5.0.3 everything works fine whit the client.Get("/me").
But when retrieving the status, I should get aan arraylist "data" with all the status messages according to the facebook Graph API, but instead my data array is empty and I get a 'Index out of bounds' exception.
Does anyone have an idea what my problem could be?
if (Request.Params["code"] != null)
{
var client = new FacebookClient(GetAccessToken());
dynamic me = client.Get("/me");
imgUser.ImageUrl = "https://graph.facebook.com/" + me.id + "/picture";
lblUsername.Text = me.name;
lblHometown.Text = me.hometown.name;
lblBirthday.Text = me.birthday;
lblCurrenttown.Text = me.location.name;
lblEmail.Text = me.email;
lblOpleidingen.Text = "";
lblOpleidingen.Text += me.education[1].type + ": " + me.education[1].school.name + ", " + me.education[1].year.name + "<br />"
+ me.education[0].type + ": " + me.education[0].school.name + ", " + me.education[0].year.name;
lblSex.Text = me.gender;
dynamic status = client.get("/me/statuses");
txtStatus.Text = status.data[0].message;
}
It requires the read_stream permission. Ensure you have it.
Your permission array should look like follows:
string[] extendedPermissions = new[] { "user_about_me", "read_stream" };
if (extendedPermissions != null && extendedPermissions.Length > 0)
{
var scope = new StringBuilder();
scope.Append(string.Join(",", extendedPermissions));
parameters["scope"] = scope.ToString();
}
furthermore your second get() should be capitalized: Get()
dynamic status = client.get("/me/statuses");
dynamic status = client.Get("/me/statuses");

Categories