ASP.NET MVC Array of Children Foreign key Non-Nullable - asp.net-mvc-3

So I have 2 Models setup like this:
class Job { ... List<Restriction> userRestrictions {set; get; ... }
2nd Model:
Restriction { public int Id { get; set; } ... public int JobID { get; set; } }
Now, when I edit a job, I fetch the Restrictions via:
job = db.Jobs.Where(i => i.Id == id).Include(r => r.UserRestrictions).First();
So I iterate through UserRestrictions and manually make them:
#for (ind = 0; ind < Model.UserRestrictions.Count; ind++)
{
JaASv1.Models.Restriction p = Model.UserRestrictions[ind];
<tr>
<td>
<input type="hidden" name="UserRestrictions[#(Counter + ind)].Id" value="#p.Id" />
<input type="hidden" name="UserRestrictions[#(Counter + ind)].JobId" value="#Model.Id" />
</td>
My Post Method:
public ActionResult Edit(Job job, string ProjTypeOther, string VenderOther, string FoldingOther, string BindingOther)
...
db.Entry(job).State = EntityState.Modified;
...
for (int iter = iterStart; iter >= 0; iter--)
{
Restriction r = job.UserRestrictions[iter];
db.Entry(r).State = EntityState.Modified;
if (r.Permissions == 0)
{
DelPermission(sPath, r.AdName); // Folder Permission things
job.UserRestrictions.Remove(r);
continue;
}
else if (r.Permissions == 1 )
{
AddPermission(sPath, r.AdName, readRights); // Folder Permission things
}
else if (r.Permissions == 2)
{
AddPermission(sPath, r.AdName, writeRights); // Folder Permission things
}
}
db.SaveChanges();
I get the following error on db.SaveChanges():
The relationship could not be changed because one or more of the
foreign-key properties is non-nullable.
I look through all the job.UserRestrictions and see they all have their JobID posted, I even looked in the database context and saw that there aren't any Foreign Keys with NULLs in them, so I don't know what this error is talking about.
Am I perhaps doing something wrong?
I've tried setting each Restriction state to Modified. That didn't seem to work.
I'm open to any suggestions.
Thanks!

So, what I ended up doing is the following:
Pulling all the UserRestrictions currently in the database.
Upon iterating through the post data, I check for the corresponding item in the database. I also set the UserRestrictions from the Post object to null so ASP doesn't try to re-insert into the table.
If the item doesn't exist, I add the item into the database.
I modify the item from the database instead of the post data one.
I had hoped ASP.NET would handle everything for me, but I guess I can't expect it to do it all.
List<Restriction> fromDB = db.Restrictions.Where(r => r.JobId == job.Id).ToList();
List<Restriction> newPost = job.UserRestrictions;
job.UserRestrictions = null;
for (int iter = iterStart; iter >= 0; iter--) {
... // Logic to handle post item
Restriction b;
try
{
b = fromDB.Where(f => f.Id == r.Id).First();
}
catch (Exception er)
{
// No record exists yet
b = r;
db.Restrictions.Add(b);
}
// Modify values of b to the values from post data
}
db.SaveChanges();
Sorry for strange indentation, StackOverflow should use bbcode instead of whitespace :x

Related

How to update related cases and fields from one recordtype to other recordtype in lead

public class UpdaterecordtypeforLead {
Public static void Leadtootherupdate() {
List<Lead> OlderLead = [SELECT Id,Name, RecordTypeId from Lead where RecordType.Name = 'Enquiries'];
List<Lead> NewLead = New List<Lead> ();
If(NewLead.Id == null)
{
for( Lead l : OlderLead) {
for(Lead l1 : NewLead) {
l1.LastName = l.LastName;
l1.Email= l.Email;
NewLead.add(l1);
NewLead.add(l1);
Insert l1;
}
}
If ( (l1. LastName == l.LastName && l1.Email == l.Email))
{
NewLead.add(OlderLead.Related_Cases__c);
NewLead.add(l.Id);
Update NewLead;
}
}
}
}
I'm getting error while saving.
I think you have a lot of issues:
What is the context / aim of this code ?
Query using DeveloperName not Name as it's language dependent
Testing if (NewLead.Id == null) when ``NewLead` is a list will not work
Looping on NewLead for what reason ?
Duplicate NewLead.add(l1)
Insert in a loop will gets you to governor limits and should be avoided, go for bulk insert
The if is outside the loop
Don't update something you just insert, instead make sure everything is okay before insert
NewLead is a list of Lead so you can't add OlderLead.Related_Cases__c or l.Id to it
Think about indenting correctly your code, it's easier for others to read
Use naming conventions
A fixed code would probably be something like this:
public class UpdateRecordtypeForLead {
public static void leadToOtherUpdate () {
List<Lead> olderLeads = [
SELECT
Id,
LastName,
Email,
RecordTypeId
FROM
Lead
WHERE
RecordType.DeveloperName = 'Enquiries'
];
List<Lead> newLeads = New List<Lead>();
for (Lead olderLead : olderLeads) {
newLeads.add(new Lead(
Id = olderLead.Id,
LastName = olderLead.LastName,
Email = olderLead.Email,
RecordTypeId = 'the_new_record_type_id'
));
}
}
update newLeads;
}
}

How to convert this to Linq?

I got another Linq problem.. Because I'm not really sure if there is another way to do this. Here is what I want to convert:
class ID
{
public string name {get; set;}
public int id {get; set;}
}
ID[] num1 = new ID[2] { {"david",1} , {"mark",2} };
ID[] num2 = new ID[3] { {"david",1} , {"david",2} };
for(int i = 0; i < num1.Length; i++)
{
for(int j = 0; j < num2.Length; j++)
{
if(num1.name.Equals(num2.name) && num1.num == num2.num)
{
Console.Writeline("name: " + num1.name + " id: " + num1.id);
//Do something
break; //to avoid useless iterations once found
}
}
}
It's not a perfect code, but hopefully it captures what I want to do. Currently I am implementing this in Linq like such:
var match =
from a in num1
from b in num2
where (a.name.Equals(b.name) && a.num == b.num)
select a;
//do something with match
I'm pretty new to Linq so I'm not sure if this is the best way to do it or is there a much more "simpler" way. Since it seems like I'm just converting it to linq but essentially does the same code.
Thank you!
The Linq code you wrote is already on the right track to solve the problem, though it is not the only way to solve it.
Instead of using a where clause, you could override the Equals method on the class, or implement an IEqualityComaprer<Number>. Then you could use the Intersect Linq method.
Something like this:
public class Number
{
public override bool Equals(object other)
{
var otherAsNumber = other as Number;
return otherAsNumber != null
&& (otherAsNumber.Name == null
? this.Name == null
: otherAsNumber.Name.Equals(this.Name)
)
&& otherAsNumber.Num == this.Num
;
}
// ...
}
// ...
var result = num1.Intersect(num2);
foreach(var item in result)
{
// Do something
}
This of course assumes that you've fixed your code so that it compiles, and so that num1 and num2 refer to collections of Number classes, instead of individual Number instances. There are a lot of problems in the code you wrote, so I'll leave fixing that problem to you.

How can I change the dropdownlist's options?

I'm a newbie in asp.net so I'm hoping you could give me some help on my dropdownlist bound to a table.
Here's the scenario:
I have a table Account with fields UserId, UserName and Type. The Type field contains 3 items: 'S', 'A', and 'U'. Each user has his own Type. I have a dropdownlist named 'ddlType' which is already
bound on the Account table. However, I want the options of the dropdownlist to be displayed as 'Stakeholder', 'Approver', and 'User' instead of displaying letters/initials only. Since I do not prefer making any changes in the database, how can I change those options through code behind?
Here's my code:
public void BindControls(int selectedUserId)
{
DataTable dtAccount = null;
try
{
dtAccount = LogBAL.GetAccountDetails(selectedUserId);
if (dtAccount.Rows.Count > 0)
{
lblUserId.Text = dtAccount.Rows[0]["UserId"].ToString();
txtUserName.Text = dtAccount.Rows[0]["UserName"].ToString();
ddlType.SelectedValue = dtAccount.Rows[0]["Type"].ToString();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
dtAccount.Dispose();
}
}
Any help from you guys will be appreciated. Thanks in advanced! :D
You can bind Dropdownlist in codebehind.
Get your data "Type" into array. Make array two dimentional and assign values to it.
After having data your array will looks like this,
string[,] Types = { { "Stakeholder", "S" }, { "Approver", "A" }, { "User", "U" } };
Now assign values to Dropdown,
int rows = Types.GetUpperBound(0);
int columns = Types.GetUpperBound(1);
ddlType.Items.Clear();
for (int currentRow = 0; currentRow <= rows; currentRow++)
{
ListItem li = new ListItem();
for (int currentColumn = 0; currentColumn <= columns; currentColumn++)
{
if (currentColumn == 0)
{
li.Text = Types[currentRow, currentColumn];
}
else
{
li.Value = Types[currentRow, currentColumn];
}
}
ddlType.Items.Add(li);
}
I haven't tested it but hopefully it will work.

Jqgrid search results pagination with Spring 3.0

I have several jqgrids running and all are functioning fine. However, when I do a search, I am only displaying ten search results per page. Whenever there are more than ten results, clicking on page two has no effect on the grid. Here is one of my controller actions, pay particular attention to the if satatement where search is true....
EDIT
I think I may have found a clue as to what may be causing my issue. You see I have several subgrids under the main grid. In terms of my java code I have object-A which has a list of object-B
, thus A has a subgrid of B. The way i am building up the json string to feed to the grid is by iterating over the list of B contained in A. I did not write a query of some kind to say order by, and limit the results etc.
So i guess the real question should be how to build a finder on a collection so that the contents can be arranged and ordered as i wish?
Here is the action I am calling for one of my entities described as B above. Pay particular attention to where i said person.getContacts()
#RequestMapping(value = "contactjsondata/{pId}", method = RequestMethod.GET)
public #ResponseBody String contactjsondata(#PathVariable("pId") Long personId, Model uiModel, HttpServletRequest httpServletRequest) {
Person person = Person.findPerson(personId);
String column = "id";
if(httpServletRequest.getParameter("sidx") != null){
column = httpServletRequest.getParameter("sidx");
}
String orderType = "DESC";
if(httpServletRequest.getParameter("sord") != null){
orderType = httpServletRequest.getParameter("sord").toUpperCase();
}
int page = 1;
if(Integer.parseInt(httpServletRequest.getParameter("page")) >= 1){
page = Integer.parseInt(httpServletRequest.getParameter("page"));
}
int limitAmount = 10;
int limitStart = limitAmount*page - limitAmount;
List<Contact> contacts = new ArrayList<Contact>(person.getContacts());
double tally = Math.ceil(contacts.size()/10.0d);
int totalPages = (int)tally;
int records = contacts.size();
StringBuilder sb = new StringBuilder();
sb.append("{\"page\":\"").append(page).append("\", \"records\":\"").append(records).append("\", \"total\":\"").append(totalPages).append("\", \"rows\":[");
boolean first = true;
for (Contact c: contacts) {
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
sb.append("]}");
return sb.toString();
}
To fix the issue with pagination you need to replace the following block of code
for (Contact c: contacts) {
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
with:
for (int i=limitStart; i<Math.min(records, limitStart+limitAmount); i++){
Contact c = contacts[i];
sb.append(first ? "" : ",");
if (first) {
first = false;
}
sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\"]}",c.getId(), c.getId(), c.getContactType().getName() ,c.getContactValue()));
}
Another option is using loadonce:true to let the jqGrid handle pagination and sorting. In this case you don't need to make changes described above

How to get out of repetitive if statements?

While looking though some code of the project I'm working on, I've come across a pretty hefty method which does
the following:
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
if (data != null)
{
if (data.A == null)
{
data.A = fieldName;
_dataRepository.InsertOrUpdate(data);
return "A";
}
if (data.B == null)
{
data.B = fieldName;
_dataRepository.InsertOrUpdate(data);
return "B";
}
// keep going data.C through data.Z doing the exact same code
}
}
Obviously having 26 if statements just to determine if a property is null and then to update that property and do a database call is
probably very naive in implementation. What would be a better way of doing this unit of work?
Thankfully C# is able to inspect and assign class members dynamically, so one option would be to create a map list and iterate over that.
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
List<string> props = new List<string>();
props.Add("A");
props.Add("B");
props.Add("C");
if (data != null)
{
Type t = typeof(data).GetType();
foreach (String entry in props) {
PropertyInfo pi = t.GetProperty(entry);
if (pi.GetValue(data) == null) {
pi.SetValue(data, fieldName);
_dataRepository.InsertOrUpdate(data);
return entry;
}
}
}
}
You could just loop through all the character from 'A' to 'Z'. It gets difficult because you want to access an attribute of your 'data' object with the corresponding name, but that should (as far as I know) be possible through the C# reflection functionality.
While you get rid of the consecutive if-statements this still won't make your code nice :P
there is a fancy linq solution for your problem using reflection:
but as it was said before: your datastructure is not very well thought through
public String DataField(int id, string fieldName)
{
var data = new { Z = "test", B="asd"};
Type p = data.GetType();
var value = (from System.Reflection.PropertyInfo fi
in p.GetProperties().OrderBy((fi) => fi.Name)
where fi.Name.Length == 1 && fi.GetValue(data, null) != null
select fi.Name).FirstOrDefault();
return value;
}
ta taaaaaaaaa
like that you get the property but the update is not yet done.
var data = _dataRepository.Find(id);
If possible, you should use another DataType without those 26 properties. That new DataType should have 1 property and the Find method should return an instance of that new DataType; then, you could get rid of the 26 if in a more natural way.
To return "A", "B" ... "Z", you could use this:
return (char)65; //In this example this si an "A"
And work with some transformation from data.Value to a number between 65 and 90 (A to Z).
Since you always set the lowest alphabet field first and return, you can use an additional field in your class that tracks the first available field. For example, this can be an integer lowest_alphabet_unset and you'd update it whenever you set data.{X}:
Init:
lowest_alphabet_unset = 0;
In DataField:
lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {
case 1:
/* A is free */
/* do something */
return 'A';
[...]
case 7:
/* A through F taken */
data.G = fieldName;
_dataRepository.InsertOrUpdate(data);
return 'G';
[...]
}
N.B. -- do not use, if data is object rather that structure.
what comes to my mind is that, if A-Z are all same type, then you could theoretically access memory directly to check for non null values.
start = &data;
for (i = 0; i < 26; i++){
if ((typeof_elem) *(start + sizeof(elem)*i) != null){
*(start + sizeof(elem)*i) = fieldName;
return (char) (65 + i);
}
}
not tested but to give an idea ;)

Resources