Creating a breadcrumb like hierarchy using LINQ - c#

I'm building a dropbox -like application to store images.
I have a database table called Images:
ImageId [PK]
ParentImageId [FK]
Name
Path
I want to create a breadcrumb from the above structure lets say I have the following data:
Is it possible using LINQ to be able to create a breadcrumb that looks like (if I am at sub folder 2)
:
Folder 1 > Sub Folder 1 > Sub Folder 2
How do I build a query to return the desired results? Any assistance would be of great help!

With Entity Framework you can do next:
And code will look like this:
var image = db.Images.FirstOrDefault(i => i.Id == currImageId);
var imagesHierarchy = new List<Image>();
if (image != null)
{
var parent = image.Parent;
while (parent != null)
{
imagesHierarchy.Insert(0, parent);
parent = parent.Parent;
}
}
var breadcrumb = string.Join(" > ", imagesHierarchy.Select(i => i.Name));

This will do it:
var current = new Record
{ ImageId = 4, ParentImageId = 3, Name = "Sub Folder 2" };
var records = new []
{
new Record { ImageId = 1, ParentImageId = 1, Name = "Folder 1" },
new Record { ImageId = 2, ParentImageId = 1, Name = "Image 1" },
new Record { ImageId = 3, ParentImageId = 1, Name = "Sub Folder 1" },
current,
new Record { ImageId = 5, ParentImageId = 4, Name = "Sub Image" },
};
var index = records.ToDictionary(r => r.ImageId);
Func<Record, IEnumerable<Record>> traverseUp = null;
traverseUp = r =>
{
var rs = new [] { r, };
if (r.ParentImageId == r.ImageId)
{
return rs;
}
else
{
return traverseUp(index[r.ParentImageId]).Concat(rs);
}
};
var breadcrumb = String.Join(" > ", traverseUp(current).Select(r => r.Name));

Related

Append property value to c# model value using LINQ

I want to return the List of records with Id and name, where the name will be appended with the domain as name(domain) if the names are non-unique and it will again append with code if domain is also non-unique, such as name(domain)(code).
To be Clear
name - for unique names,
name(domain) - for duplicated names
name(domain)(code) - for duplicated codes.
Below are the sample data and expected data
**Sample Data**
var filter = new List<Record>()
{
new Record { Id = 011, Name = "OAKLAWN", Code = 123, Domain = "p1000"},
new Record { Id = 012, Name = "OAKLAWN", Code = 124 , Domain = "p2000"},
new Record { Id = 013, Name = "OAKLAWN", Code = 125 , Domain = "p3000"},
new Record { Id = 014, Name = "OAKLAWN", Code = 126 , Domain = "p4000"},
new Record { Id = 015, Name = "OAKLAWN", Code = 127 , Domain = "p5000"},
new Record { Id = 016, Name = "PEAKLAWN", Code = 111 , Domain = "p6000"},
new Record { Id = 017, Name = "PERKLAWN", Code = 124 , Domain = "p6000"},
new Record { Id = 018, Name = "QUCKLAWN", Code = 122 , Domain = "p6000"}
};
**expected return data**
{ Id = 011, Name = "OAKLAWN(p1000)"},
{ Id = 012, Name = "OAKLAWN(p2000)(124)"},
{ Id = 013, Name = "OAKLAWN(p3000)"},
{ Id = 014, Name = "OAKLAWN(p2000)(126)"},
{ Id = 015, Name = "OAKLAWN(p5000)"},
{ Id = 016, Name = "PEAKLAWN"},
{ Id = 017, Name = "PERKLAWN"},
{ Id = 018, Name = "QUCKLAWN"}
How can I achieve this using c# LINQ.
.NET fiddle: https://dotnetfiddle.net/2UdaxY
Thanks.
var records = filter.GroupBy(
r => r.Name,
(key, group) => group.Select(r => new
{
r.Id,
Name = group.Count() == 1
? key
: group.Count(x => x.Domain == r.Domain) == 1
? $"{key}({r.Domain})"
: $"{key}({r.Domain})({r.Code})"
})
)
.SelectMany(r => r)
.ToArray();
.NET fiddle: https://dotnetfiddle.net/tIPZOR

Get list of files in a specific Netsuite folder

I'm trying to retrieve a list of files in a specific folder in the file cabinet. When I execute the search, I'm given all files in the specified folder and all folders underneath that folder. I've tried with FileSearchBasic and FileSearchAdvanced, both give me the same results.
Is there a way to get only files in the specified folder id?
var search = new FileSearchBasic
{
folder = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
#operatorSpecified = true,
searchValue = new[] { new RecordRef
{
internalId = "1234"
}}
}
};
var result = ns.search(search);
if (result.status.isSuccess)
{
foreach (var record in result.recordList)
{
if (record is File file)
{
Console.WriteLine($"{file.folder.internalId} - {file.name}");
}
}
}
This code results in the following list where folder 1236 is a sub folder of folder 1234
1234 - lodash.js
1234 - dt.timer.js
1234 - dt.search.js
1234 - dt.customer.js
1234 - dt.safeExecute.js
1236 - processRawLocationData.js
I was able to get only the files in the specified folder by performing a FolderSearchAdvanced() and using a file join rather than a FileSearchAdvanced(). It sort of makes sense since you have to do it this way in SuiteScript as well.
Still open to alternative methods.
var search = new FolderSearchAdvanced()
{
criteria = new FolderSearch()
{
basic = new FolderSearchBasic()
{
internalId = new SearchMultiSelectField()
{
#operator = SearchMultiSelectFieldOperator.anyOf,
searchValue = new[] { searchValue },
operatorSpecified = true
},
}
},
columns = new FolderSearchRow
{
basic = new FolderSearchRowBasic()
{
internalId = new[] { new SearchColumnSelectField() },
name = new [] { new SearchColumnStringField() }
},
fileJoin = new FileSearchRowBasic()
{
internalId = new[] { new SearchColumnSelectField() },
name = new[] { new SearchColumnStringField() },
modified = new[] { new SearchColumnDateField() },
documentSize = new[] { new SearchColumnLongField() }
}
}
};
var results = ns.search(search);
if (results.status.isSuccess)
{
foreach (var result in results.searchRowList)
{
if (result is FolderSearchRow row)
{
var fileId = row.fileJoin.internalId[0].searchValue.internalId;
var fileName = row.fileJoin.name[0].searchValue;
Console.WriteLine($"{fileId} - {fileName}");
}
}
}

LAMBDA C# union informations

Using C# with Lambda(or some method), how can I merge different informations(from columns) of the same intituition name ? They can have some common and some different fields.
See a example below:
Have you tried the Group By instruction ?
Here is an other stackoverflow about this : Group by in LINQ
{
List<Instituition> Instituitions = new List<Instituition>() {
new Instituition { Name = "Name1", Alias = "",Area="" },
new Instituition { Name = "Name1", Alias = "Alias1",Area="" },
new Instituition { Name = "name2", Alias = "Audi" ,Area="444"},
new Instituition { Name = "Name1", Alias = "",Area="Garden" }};
var results = Instituitions.GroupBy(i => i.Name,
i => i.Alias,
(key, g) => new
{
Name = key,
Alias = g.Where(a =>a != "").FirstOrDefault(),
Area = Instituitions.Where(a=>a.Name == key && a.Area != "").Select(a=>a.Area).FirstOrDefault()
}
);
}
class Instituition
{
internal string Name;
internal string Alias;
internal string Area;
}

c# Listitems dont add if exisit in array

I have an array of days (mon, tue, etc..) that I might not want to show, so when I create a list of days, if they are already in the "hiddendays", it doesn't add them.
// This would return for example 1, 2
var hDays = account.ScheduleHiddenDays.Split(',').Select(int.Parse).ToList();
var daySunday = new ViewModels.Day()
{
Id = 0,
Name = "Sunday"
};
var dayMonday = new ViewModels.Day()
{
Id = 1,
Name = "Monday"
};
var dayTuesday = new ViewModels.Day()
{
Id = 2,
Name = "Tueday"
};
var dayWednesday = new ViewModels.Day()
{
Id = 3,
Name = "Wednesday"
};
var dayThursday = new ViewModels.Day()
{
Id = 4,
Name = "Thursday"
};
var dayFriday = new ViewModels.Day()
{
Id = 5,
Name = "Friday"
};
var daySaturday = new ViewModels.Day()
{
Id = 6,
Name = "Saturday"
};
// This is where I need to check if they exist in hDays, it doesn't add them to this list. But how?
model.ScheduleHiddenDays = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
Something along the lines of this:
var days = new List<ViewModels.Day>()
{
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
};
model.ScheduleHiddenDays = days.Where(x => !hDays.Contains(x.Id)).ToList();

How do I use Linq to query nested dynamic BsonDocuments?

public class Foo
{
public ObjectId _id { get; set; }
public BsonDocument properties { get; set; }
}
public void FindFoos()
{
var client = new MongoClient(ConfigurationManager.ConnectionStrings["MongoDB"].ConnectionString);
var server = client.GetServer();
var db = server.GetDatabase("FooBar");
//var collection = db.GetCollection<GeoJsonFeature<GeoJson2DGeographicCoordinates>>("Sections");
var collection = db.GetCollection<Foo>("Foos");
collection.Insert(new Foo
{
properties = new BsonDocument{
{"Foo" , "foo1"},
{"Bar" , "bar1"}
}
});
collection.Insert(new Foo
{
properties = new BsonDocument{
{"Foo" , "foo2"},
{"Bar" , "bar2"}
}
});
var query = Query<Foo>.Where(foo => foo.properties.AsQueryable().Any(property => property.Name == "Foo" && property.Value.AsString == "foo1"));
var result = collection.Find(query).First();
}
calling FindFoos results in the following exception:
Unsupported where clause: Queryable.Any(Queryable.AsQueryable(foo.properties), (BsonElement property) => ((property.Name == "Foo") && (property.Value.AsString == "foo1"))).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: Unsupported where clause: Queryable.Any(Queryable.AsQueryable(foo.properties), (BsonElement property) => ((property.Name == "Foo") && (property.Value.AsString == "foo1"))).
at the line:
var query = Query<Foo>.Where(foo => foo.properties.AsQueryable().Any(property => property.Name == "Foo" && property.Value.AsString == "foo1"));
I can do this query easily in the mongodb shell as:
db.Foos.find( {'properties.Foo' : 'foo1'} );
What is the correct way to do this query with Linq?
Try LINQ's SelectMany() method. It is used to flatten nested collections. Instead of using nested for loops, we can do the task in a more 'LINQ' way.
Ex given below -
Master m1 = new Master() { name = "A", lstObj = new List<obj> { new obj { i = 1, s = "C++" }, new obj { i = 1, s = "C#" }, new obj { i = 1, s = "Java" } } };
Master m2 = new Master() { name = "A", lstObj = new List<obj> { new obj { i = 4, s = "PHP" }, new obj { i = 5, s = "Ruby" }, new obj { i = 6, s = "Perl" } } };
List<Master> lstMasters = new List<Master> { m1, m2 };
var result = lstMasters.SelectMany(m => m.lstObj).Where(o => o.s == "PHP");
Just replace the Master class with your BsonDocument.

Categories