Mapping lack of understanding - mapping

I read a lot about this topic and I understand it quit good.
But, the only thing I don't understand is how in functions developers use it without a function that insert the values.
example:
mapping (uint256=>address) public IdToAddress;
after they defines it I see that they are using in functions like:
function HolderOfNFT(Uint256 Id) public returns (address) {
return IdToAddress[Id];
}
How the mapping has value in the Id key that points to the right address?
Thanks a lot!!

All mapping values are empty by default.
So unless the value is set somewhere in the code, your example would return address(0) for any Id.
You can assign a mapping value the same way as you'd assign it to an array. Examples:
IdToAddress[Id] = address(0x123);
function transfer(address _recipient, uint256 _id) public {
require(IdToAddress[_id] == msg.sender, "You're not the current token owner");
IdToAddress[_id] = _recipient;
}

Related

Unable to get a mapping value

I'm trying to implement a small contract to upload file hashes on the blockchain along with the file description and the sender address. I've programmed this small contract :
pragma solidity^0.4.17;
contract hashes {
mapping(uint => string) descriptions;
mapping(uint => address) senderAddresses;
function uploadHash(uint _hash, string _description) public {
require(bytes(descriptions[_hash]).length == 0);
descriptions[_hash] = _description;
senderAddresses[_hash] = msg.sender;
}
function getHash(uint _hash) public returns (address, string){
return (senderAddresses[_hash], descriptions[_hash]);
}
}
I think uploadHash works as expected since when I'm uploading the same hash twice I get a revert. However when I'm trying to use getHash, I don't get any return value. The results are the same when I'm calling from remix or directly from web3.
Thanks in advance !
I believe you're missing the view modifier
function getHash(uint _hash) public view returns (address, string)
Remix will not show the res next to the input boxes unless you use the view modifier.

C# MVC Link-To-Sql passing table name and field name to function

I am writing an ASP.NET MVC (C#, SQL Server) web site and would like to write a function in my controller in which I pass a table name, a column name, and a value to check against the passed in column name in the passed in table.
If the record is found, I want to return the primary key of the record.
If the value is not found in the table, I want to create it and then return the primary key of that record.
private int FindRecord(string tableName, string FieldToCheck, string LookupValue)
{
/* 1) How do I set the string 'tableName' to a table in my context */
/* How do I set the string FieldToCheck to a field in the 'tableName' */
/* How do I return the primary key if LookupValue is in 'FieldToCheck' */
/* How do I add a record and return primary key if it is now */
return PrimaryKeyOfFoundOrNewRecord;
}
I almost cannot imagine that this question is not a duplicate but I cannot find any examples - perhaps I'm not using the proper terms to search. Thank you in advance.
OK, based on the comment clarification of what is required, then what you might want is something like this:
void CreateLocation(string city,string state, string country)
{
var newLoc = new Location();
newLoc.City = GetCity(city);
if (newLoc.City == null)
{
newLoc.City = new City() { Name = city });
}
//Repeaat this for state and country.
_context.Locations.Add(newLoc);
_context.SaveChanges();
}
City GetCity(string city)
{
var city = from c in _context.Cities
where c.name.Equals(city)
select c;
return city.FirstOrDefault();
}
Apologies if the syntax is a little off, nearly quitting time here.
Sorry, some of this syntax might be entity framework as opposed to linq-to-sql - just noticed your tag. Syntax is different (marginally) but idea is the same.

how to remove a node from linked list using recursion?

I need to remove a node from a linked list using recursion. this is the code that I have so far...
public class SortedSetNode implements Set {
protected String value;
protected SortedSetNode next;
public boolean remove(String element) {
if (value.equals(element))
{
next = next.getNext();
return true;
}
else
{
return next.remove(element);
}
}
Well, without knowing what the problem is that you are facing, you would need a clause in there to check whether the item you are removing is actually in the linked list, i.e.
if(next == null){
return false;
}
Other than that your code looks fine. What is the issue you are encountering?
If the value attribute is the value of the current node, then you'll need to delete itself when value equals element, rather than delete the next. Unless it's the value of next node.
You might need a start point, so when you compare value, you compare the next node's value with the string, and if found, do your next = next.getNext();. Of course a check of null is needed.

What is the best way to assign the String.Empty values to the property if it is Null using asp.net mvc

I have a column in the database which is Name its string with null value.
when I dont enter anything in the Name Field its saving to the database as NULL.
but I need to save this value as string.Empty or "".
I did soemthing like this.
h.assignedName= m.Name== null ? string.Empty : m.Name;
ViewModel Property has
Public string Name {get;set;}
my question is any other way we can assign this value has String.Empty without doing any condition like above?
I dont want to use ? operator to check the condition or if condition.
Thanks
You could change the column in the database to not be NULL and set the default value to ''. That way you would not have to use the ? conditional. Not sure if this is best practise, but it would save you having to add additional code to cater for it.
The other way is to create a wrapper class around the data. I see you're using m.Name in your code example. You could have:
public class MyWrapper
{
private string _name;
public string Name
{
get {
if (String.IsNullOrEmpty(_name)){
return String.Empty;
}
return _name;
}
set{
_name = value;
}
}
}
So when you're reading the data from the database, create an instance of your wrapper class to hide the details when getting the Name.
Jason's idea is sound assuming you do not care about making that minor change.
Another way you could do it is to abandon your automatic property and handle the checking in the get
private string name;
public string Name
{
get { return (name == null) ? string.Empty : name; }
}
This obviously has more initial code over head for all properties that you want to utilize this style.
or you could ensure it is never null in your constructors
You might consider changing the layout of your code construction and use a business rule like
"m.Name may never be null." And then you should initialize it as String.Empty, so that it can never be null.

Json and Circular Reference Exception

I have an object which has a circular reference to another object. Given the relationship between these objects this is the right design.
To Illustrate
Machine => Customer => Machine
As is expected I run into an issue when I try to use Json to serialize a machine or customer object. What I am unsure of is how to resolve this issue as I don't want to break the relationship between the Machine and Customer objects. What are the options for resolving this issue?
Edit
Presently I am using Json method provided by the Controller base class. So the serialization I am doing is as basic as:
Json(machineForm);
Update:
Do not try to use NonSerializedAttribute, as the JavaScriptSerializer apparently ignores it.
Instead, use the ScriptIgnoreAttribute in System.Web.Script.Serialization.
public class Machine
{
public string Customer { get; set; }
// Other members
// ...
}
public class Customer
{
[ScriptIgnore]
public Machine Machine { get; set; } // Parent reference?
// Other members
// ...
}
This way, when you toss a Machine into the Json method, it will traverse the relationship from Machine to Customer but will not try to go back from Customer to Machine.
The relationship is still there for your code to do as it pleases with, but the JavaScriptSerializer (used by the Json method) will ignore it.
I'm answering this despite its age because it is the 3rd result (currently) from Google for "json.encode circular reference" and although I don't agree with the answers (completely) above, in that using the ScriptIgnoreAttribute assumes that you won't anywhere in your code want to traverse the relationship in the other direction for some JSON. I don't believe in locking down your model because of one use case.
It did inspire me to use this simple solution.
Since you're working in a View in MVC, you have the Model and you want to simply assign the Model to the ViewData.Model within your controller, go ahead and use a LINQ query within your View to flatten the data nicely removing the offending circular reference for the particular JSON you want like this:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other Machine properties you desire
Customer = new { m.Customer.Id, m.Customer.Name, // other Customer properties you desire
}};
return Json(jsonMachines);
Or if the Machine -> Customer relationship is 1..* -> * then try:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other machine properties you desire
Customers = new List<Customer>(
(from c in m.Customers
select new Customer()
{
Id = c.Id,
Name = c.Name,
// Other Customer properties you desire
}).Cast<Customer>())
};
return Json(jsonMachines);
Based on txl's answer you have to
disable lazy loading and proxy creation and you can use the normal methods to get your data.
Example:
//Retrieve Items with Json:
public JsonResult Search(string id = "")
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var res = db.Table.Where(a => a.Name.Contains(id)).Take(8);
return Json(res, JsonRequestBehavior.AllowGet);
}
Use to have the same problem. I have created a simple extension method, that "flattens" L2E objects into an IDictionary. An IDictionary is serialized correctly by the JavaScriptSerializer. The resulting Json is the same as directly serializing the object.
Since I limit the level of serialization, circular references are avoided. It also will not include 1->n linked tables (Entitysets).
private static IDictionary<string, object> JsonFlatten(object data, int maxLevel, int currLevel) {
var result = new Dictionary<string, object>();
var myType = data.GetType();
var myAssembly = myType.Assembly;
var props = myType.GetProperties();
foreach (var prop in props) {
// Remove EntityKey etc.
if (prop.Name.StartsWith("Entity")) {
continue;
}
if (prop.Name.EndsWith("Reference")) {
continue;
}
// Do not include lookups to linked tables
Type typeOfProp = prop.PropertyType;
if (typeOfProp.Name.StartsWith("EntityCollection")) {
continue;
}
// If the type is from my assembly == custom type
// include it, but flattened
if (typeOfProp.Assembly == myAssembly) {
if (currLevel < maxLevel) {
result.Add(prop.Name, JsonFlatten(prop.GetValue(data, null), maxLevel, currLevel + 1));
}
} else {
result.Add(prop.Name, prop.GetValue(data, null));
}
}
return result;
}
public static IDictionary<string, object> JsonFlatten(this Controller controller, object data, int maxLevel = 2) {
return JsonFlatten(data, maxLevel, 1);
}
My Action method looks like this:
public JsonResult AsJson(int id) {
var data = Find(id);
var result = this.JsonFlatten(data);
return Json(result, JsonRequestBehavior.AllowGet);
}
In the Entity Framework version 4, there is an option available: ObjectContextOptions.LazyLoadingEnabled
Setting it to false should avoid the 'circular reference' issue. However, you will have to explicitly load the navigation properties that you want to include.
see: http://msdn.microsoft.com/en-us/library/bb896272.aspx
Since, to my knowledge, you cannot serialize object references, but only copies you could try employing a bit of a dirty hack that goes something like this:
Customer should serialize its Machine reference as the machine's id
When you deserialize the json code you can then run a simple function on top of it that transforms those id's into proper references.
You need to decide which is the "root" object. Say the machine is the root, then the customer is a sub-object of machine. When you serialise machine, it will serialise the customer as a sub-object in the JSON, and when the customer is serialised, it will NOT serialise it's back-reference to the machine. When your code deserialises the machine, it will deserialise the machine's customer sub-object and reinstate the back-reference from the customer to the machine.
Most serialisation libraries provide some kind of hook to modify how deserialisation is performed for each class. You'd need to use that hook to modify deserialisation for the machine class to reinstate the backreference in the machine's customer. Exactly what that hook is depends on the JSON library you are using.
I've had the same problem this week as well, and could not use anonymous types because I needed to implement an interface asking for a List<MyType>. After making a diagram showing all relationships with navigability, I found out that MyType had a bidirectional relationship with MyObject which caused this circular reference, since they both saved each other.
After deciding that MyObject did not really need to know MyType, and thereby making it a unidirectional relationship this problem was solved.
What I have done is a bit radical, but I don't need the property, which makes the nasty circular-reference-causing error, so I have set it to null before serializing.
SessionTickets result = GetTicketsSession();
foreach(var r in result.Tickets)
{
r.TicketTypes = null; //those two were creating the problem
r.SelectedTicketType = null;
}
return Json(result);
If you really need your properties, you can create a viewmodel which does not hold circular references, but maybe keeps some Id of the important element, that you could use later for restoring the original value.

Resources