I have another question for the IL sub-community.
I am finding my way through ILArrays and similar, but I would like another clarification.
In the example reported on the ILNumerics website, we have (simplifying what is not needed)
public class Computing_Module1 : ILMath
{
public static ILRetArray<double> SimpleMethod()
{ using (ILScope.Enter() )
{
ILArray<double> C = ILSpecialData.sinc(40, 50);
return C[0, full];
}
}
}
If you run this code everything works perfectly because of the final C[0,full], from what I can understand. On converse, I have the following wrapping code around ILMath.csvread:
public static ILRetArray<double> ReadCsvIL(string aFileName)
{
using (ILScope.Enter())
{
string stringData;
try
{ stringData = getDataFromText(aFileName);
ILArray<double> myData = ILMath.csvread<double>(stringData);
return myData ;
}
catch (FileNotFoundException anExc)
{
Console.WriteLine(anExc.Message);
return null;
}
}
}
That will not work: two workarounds: either use the same trick provided in the example substituting
ILArray<double> myData = ILMath.csvread<double>(stringData);
return myData ;
with
ILArray<double> myData = ILMath.csvread<double>(stringData);
return myData[ILMath.full, ILMath.full] ;
or adopting the .a property of the ILArrays, so it should be written as:
ILArray<double> myData = ILMath.csvread<double>(stringData);
myData.a = myData;
return myData ;
Question: do we always have to use the .a property to assign an ILRetArray? Am I right in understanding that if return anArray[full, full] then some deep copy is performed behind the scenes, basically assigning to the .a property? Are there other ways to do this and what is the most efficient way?
For completeness the function to retrieve the text from the file is just a wrapping function around streamreader.ReadToEnd(), here it is the code:
public static string getDataFromText(string aFileName)
{
if (!File.Exists(aFileName))
throw new FileNotFoundException("The file does not exist.");
string stringData = String.Empty;
using (StreamReader streamReader = new StreamReader(aFileName))
{
stringData = streamReader.ReadToEnd();
}
return stringData;
}
Hope this makes sense; thanks you very much in advance.
Related
I want to sort anarray by the object type. So all songs are together, all book are together, and all movies are together.
I am reading a file and determine what each object should be. then creating the object and adding it to the array.
EDIT: Here is the actual code.
static Media[] ReadData()
{
List<Media> things = new List<Media>();
try
{
String filePath = "resources/Data.txt";
string Line;
int counter = 0; // used to check if you have reached the max
number of allowed objects (100)
using (StreamReader File = new System.IO.StreamReader(filePath))
{
while ((Line = File.ReadLine()) != null)
{
This is where each object is created. The file
search for a key word in the beginning of the line, then
creates the corresponding object. It will split the
information on the first line of the object and will
read each line until a "-" character is found and
pass each line into the summary. The summary is then
decrypted and the created object is passed into an
array List. Finally if the array list reaches 100, it
will print "You have reach max number of objects" and
stop reading the file.
if (Line.StartsWith("BOOK"))
{
String[] tempArray = Line.Split('|');
//foreach (string x in tempArray){Console.WriteLine(x);} //This is used
for testing
Book tempBook = new Book(tempArray[1],
int.Parse(tempArray[2]), tempArray[3]);
while ((Line = File.ReadLine()) != null)
{
if (Line.StartsWith("-")){break;}
tempBook.Summary = tempBook.Summary + Line;
}
tempBook.Summary = tempBook.Decrypt();
things.Add(tempBook);
counter++;
}
else if (Line.StartsWith("SONG"))
{
String[] tempArray = Line.Split('|');
//foreach (string x in tempArray)
{Console.WriteLine(x);} //This is used for testing
Song tempSong = new Song(tempArray[1],
int.Parse(tempArray[2]), tempArray[3], tempArray[4]);
things.Add(tempSong);
counter++;
}
else if (Line.StartsWith("MOVIE"))
{
String[] tempArray = Line.Split('|');
//foreach (string x in tempArray)
{Console.WriteLine(x);} //This is used for testing
Movie tempMovie = new Movie(tempArray[1],
int.Parse(tempArray[2]), tempArray[3]);
while ((Line = File.ReadLine()) != null)
{
if (Line.StartsWith("-")) { break; }
tempMovie.Summary = tempMovie.Summary + Line;
}
tempMovie.Summary = tempMovie.Decrypt();
things.Add(tempMovie);
counter++;
}
if (counter == 100)
{
Console.WriteLine("You have reached the maximum number of media
objects.");
break;
}
}
File.Close();
}
}
return things.ToArray(); // Convert array list to an Array and return the
array.
}
In the main code, I have this:
Media[] mediaObjects = new Media[100];
Media[] temp = ReadData();
int input; // holds the input from a user to determin which action to take
for (int i = 0; i<temp.Length;i++){ mediaObjects[i] = temp[i]; }
I want the array of mediaObjects to be sorted by the what type of objects.
I have also used Icomparable to do an arrayList.sort() but still no luck.
public int CompareTo(object obj)
{
if (obj == null)
{
return 1;
}
Song temp = obj as Song;
if (temp != null)
{
//Type is a string
return this.Type.CompareTo(temp.Type);
}
else
{
return 1;
}
}
So I see you have BOOK, SONG and MOVIE types.
This is a classic case of implementing the IComparable interface - although you are correct with the interface name to implement, you are not using this correctly.
Create a base class by the name MediaObject - this will be the main one for your other types of objects you create.
Add the correct properties you need. In this case, the media type is the one in need.
Let this class implement IComparable to help you with the comparison.
override the CompareTo() method in the PROPER way
public class MediaObject : IComparable
{
private string mediaType;
public string MediaType
{
get {return mediaType;}
set {mediaType=value;}
}
public MediaObject(string mType)
{
MediaType = mType;
}
int IComparable.CompareTo(object obj)
{
MediaObject mo = (MediaObject)obj;
return String.Compare(this.MediaType,mo.MediaType); //implement a case insensitive comparison if needed (for your research)
}
}
You can now compare the MediaObject objects In your main method directly.
Thank for the advice. I ended up just reformating how I was creating the list while reading it. I made multiple lists for each object then just happened each one on to the master list so It showed up sorted. I wish I figured that out before I made this long post.
As far as I could find, you can't sort by the type of object in a generic array. If anyone has a better solution feel free to post it.
How may I avoid to duplicate the code I use for mapping a database entity to a poco object?
Given this code:
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
}
}).AsQueryable();
}
Can I create a common linq expression to be re-used for both methods?
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = ...???
}).AsQueryable();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return (from dt in Entities.dummy_table
select new DummyAlsoExtended
{
InnerHtml = dt.table_html.description,
Dummy = ....??
}).AsQueryable();
}
Example:
public static Expression<Func<dummy_table, Dummy>> EntityToPoco()
{
return d => new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
};
}
I can't quite get it right
....
Dummy = ExtensionClass.EntityToPoco()
So you have a dummy_table which is a Enumerable or Queryable sequence of objects. Let's assume that the sequence contains objects of class DummyTableElement.
You showed, that if you have a DummyTableElement you know how to convert it into a Dummy object. You want to reuse this function to create other objects like DummyExtended and DummyAlsoExtended. If you want to do this LINQ-alike, it is best to create extension functions for it:
static class DummyTableElementExtensions
{
public static Dummy ToDummy(this TableElement tableElement)
{
return new Dummy()
{
Name = tableElement.name,
Notes = tableElement.notes,
HelpText = tableElement.help_text
};
}
}
Once you have this, you can create similar functions to convert TableElements into DummyExtended and DummyAlsoExtended. They will be one-liners.
In the same extension class:
public static DummyExtended ToDummyExtended(this TableElement tableElement)
{
return new DummyExtended()
{
Description = tableElement.table_1.table_2.description,
Dummy = tableElement.ToDummy(),
};
}
public static DummyAlsoExtended ToDummyAlsoExtended(this TableElement tableElement)
{
return new DummyAlsoExtended
{
InnerHtml = tableElement.table_html.description,
Dummy = tableElement.ToDummy(),
};
}
And once you've got these, you can create extension functions to convert any IQueryable of TableElements:
public static IQueryable<DummyExtended> ToDummyExtended(
this IQueryable<TableElement> tableElements)
{
return tableElements
.Select(tableElement => tableelement.ToDummyExtended();
}
And a similar one-line function for DummyAlsoExtended.
Your Find function and FindAnother function will also be one-liners:
private IQueryable<DummyExtended> Find()
{
return dummy_table.ToDummyExtended();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return dummy_table.ToDummyAlsoExtended();
}
I'm not sure why you wanted to use an expression in this. It doesn't seem that DummyExtended and DummyAlsoExtended are really similar, except that they both have a property Dummy.
One reason to parameterize the destination of your find function could be because you want to create anonymous classes in your Find function.
Again, once you've created ToDummy this will be a one-liner:
public static IQueryable<TResult> Find<TSource, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TResult>> resultSelector)
{
return source.Select(sourceElement => resultSelector(sourceElement);
}
Usage would be:
var X = dummy_Table.find(tableElement => new
{
foo = tableElement.CalculateFoo(),
bar = tableElement.CalculateBar(),
Dummy = tableElement.ToDummy(),
});
I am trying to build an email template. I got what is suppose to be working example but I am having problems trying to get FormatWith() to resolve in one of the functions.
private static string PrepareMailBodyWith(string templateName, params string[] pairs)
{
string body = GetMailBodyOfTemplate(templateName);
for (var i = 0; i < pairs.Length; i += 2)
{
// wonder if I can bypass Format with and just use String.Format
body = body.Replace("<%={0}%>".FormatWith(pairs[i]), pairs[i + 1]);
//body = body.Replace("<%={0}%>",String.Format(pairs[i]), pairs[i + 1]);
}
return body;
}
It looks like an extension method to me.
You need to reference the namespace the extension method lives in at the top of your file.
Example:
namespace MyApp.ExtensionMethods
{
public class MyExtensions
{
public static string FormatWith(this string target, params object[] args)
{
return string.Format(Constants.CurrentCulture, target, args);
}
}
}
...
using MyApp.ExtensionMethods;
...
private static string PrepareMailBodyWith(string templateName, params string[] pairs)
{
string body = GetMailBodyOfTemplate(templateName);
for (var i = 0; i < pairs.Length; i += 2)
{
// wonder if I can bypass Format with and just use String.Format
body = body.Replace("<%={0}%>".FormatWith(pairs[i]), pairs[i + 1]);
//body = body.Replace("<%={0}%>",String.Format(pairs[i]), pairs[i + 1]);
}
return body;
}
Try using String.Format() instead, like you suggested...
body = body.Replace(String.Format("<%={0}%>", pairs[i]), String.Format("<%={0}%>", pairs[i+1]);
This assumes you want both the search string and the replacement string to be formatted.
I found it was easier to use the .Replace() then to jump through all the other hoops. Thank you for your suggestions.
string email = emailTemplate
.Replace("##USERNAME##", userName)
.Replace("##MYNAME##", myName);
This seems to be the simplest solution to my email template issue.
I have a path "$/Folder1/Folder2/Folder3/File.xml" I would like to get the path minus "File.xml" i.e. "$/Folder1/Folder2/Folder3".
I have written the following method,
public string GetFilePathFromFolderPath(string serverPath)
{
var folders = serverPath.Split('/').ToList();
folders.RemoveAt(folders.Count - 1);
return folders.Aggregate(string.Empty,
(current, folder) =>
!string.IsNullOrEmpty(current)
? string.Format("{0}/{1}", current, folder)
: string.Format("{0}", folder));
}
Is there a better way to do this?
My Unit Test works fine but I would like to know if there is a simple way...
[TestMethod()]
public void GetRootPathFromConfigFilePath_Validate()
{
var t = new Twrar();
var a = t.GetFilePathFromFolderPath("$/Quan/Maa/CSr/mai.py");
Assert.IsTrue(a == "$/Quan/Maa/CSr");
}
I assume you mean to use "/" as the path separator character even though it is "\" for Windows.
Dim s = "$/Quan/Maa/CSr///mai.py"
Console.WriteLine(System.IO.Path.GetDirectoryName(s).Replace("\"c, "/"c))
outputs $/Quan/Maa/CSr
The following is Tarun Arora's edit:
For C# this should be...
public string GetFilePathFromFolderPath(string serverPath)
{
return Path.GetDirectoryName(serverPath).Replace("\\", "/");
}
And all of my unit tests pass this...
[TestMethod()]
public void GetRootPathFromConfigFilePath_Validate()
{
var t = new TfsWrapper();
var a = t.GetFilePathFromFolderPath("$/Quan/Maa/CSr/mai.py");
Assert.IsTrue(a == "$/Quan/Maa/CSr");
}
[TestMethod()]
public void GetRootPathFromConfigFilePath_SmallPath()
{
var t = new TfsWrapper();
var a = t.GetFilePathFromFolderPath("$/Quan/mai.py");
Assert.IsTrue(a == "$/Quan");
}
[TestMethod()]
public void GetRootPathFromConfigFilePath_RootPath()
{
var t = new TfsWrapper();
var a = t.GetFilePathFromFolderPath("$/mai.py");
Assert.IsTrue(a == "$");
}
I have this method:
private static string GetPath(string fullPath)
{
string file = System.IO.Path.GetFileName(fullPath);
return fullPath.Replace(file, "");
}
I realize that a lot of questions have been asked relating to full text search and Entity Framework, but I hope this question is a bit different.
I am using Entity Framework, Code First and need to do a full text search. When I need to perform the full text search, I will typically have other criteria/restrictions as well - like skip the first 500 rows, or filter on another column, etc.
I see that this has been handled using table valued functions - see http://sqlblogcasts.com/blogs/simons/archive/2008/12/18/LINQ-to-SQL---Enabling-Fulltext-searching.aspx. And this seems like the right idea.
Unfortunately, table valued functions are not supported until Entity Framework 5.0 (and even then, I believe, they are not supported for Code First).
My real question is what are the suggestions for the best way to handle this, both for Entity Framework 4.3 and Entity Framework 5.0. But to be specific:
Other than dynamic SQL (via System.Data.Entity.DbSet.SqlQuery, for example), are there any options available for Entity Framework 4.3?
If I upgrade to Entity Framework 5.0, is there a way I can use table valued functions with code first?
Thanks,
Eric
Using interceptors introduced in EF6, you could mark the full text search in linq and then replace it in dbcommand as described in http://www.entityframework.info/Home/FullTextSearch:
public class FtsInterceptor : IDbCommandInterceptor
{
private const string FullTextPrefix = "-FTSPREFIX-";
public static string Fts(string search)
{
return string.Format("({0}{1})", FullTextPrefix, search);
}
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
RewriteFullTextQuery(command);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
RewriteFullTextQuery(command);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public static void RewriteFullTextQuery(DbCommand cmd)
{
string text = cmd.CommandText;
for (int i = 0; i < cmd.Parameters.Count; i++)
{
DbParameter parameter = cmd.Parameters[i];
if (parameter.DbType.In(DbType.String, DbType.AnsiString, DbType.StringFixedLength, DbType.AnsiStringFixedLength))
{
if (parameter.Value == DBNull.Value)
continue;
var value = (string)parameter.Value;
if (value.IndexOf(FullTextPrefix) >= 0)
{
parameter.Size = 4096;
parameter.DbType = DbType.AnsiStringFixedLength;
value = value.Replace(FullTextPrefix, ""); // remove prefix we added n linq query
value = value.Substring(1, value.Length - 2);
// remove %% escaping by linq translator from string.Contains to sql LIKE
parameter.Value = value;
cmd.CommandText = Regex.Replace(text,
string.Format(
#"\[(\w*)\].\[(\w*)\]\s*LIKE\s*#{0}\s?(?:ESCAPE N?'~')",
parameter.ParameterName),
string.Format(#"contains([$1].[$2], #{0})",
parameter.ParameterName));
if (text == cmd.CommandText)
throw new Exception("FTS was not replaced on: " + text);
text = cmd.CommandText;
}
}
}
}
}
static class LanguageExtensions
{
public static bool In<T>(this T source, params T[] list)
{
return (list as IList<T>).Contains(source);
}
}
For example, if you have class Note with FTS-indexed field NoteText:
public class Note
{
public int NoteId { get; set; }
public string NoteText { get; set; }
}
and EF map for it
public class NoteMap : EntityTypeConfiguration<Note>
{
public NoteMap()
{
// Primary Key
HasKey(t => t.NoteId);
}
}
and context for it:
public class MyContext : DbContext
{
static MyContext()
{
DbInterception.Add(new FtsInterceptor());
}
public MyContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public DbSet<Note> Notes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new NoteMap());
}
}
you can have quite simple syntax to FTS query:
class Program
{
static void Main(string[] args)
{
var s = FtsInterceptor.Fts("john");
using (var db = new MyContext("CONNSTRING"))
{
var q = db.Notes.Where(n => n.NoteText.Contains(s));
var result = q.Take(10).ToList();
}
}
}
That will generate SQL like
exec sp_executesql N'SELECT TOP (10)
[Extent1].[NoteId] AS [NoteId],
[Extent1].[NoteText] AS [NoteText]
FROM [NS].[NOTES] AS [Extent1]
WHERE contains([Extent1].[NoteText], #p__linq__0)',N'#p__linq__0 char(4096)',#p__linq__0='(john)
Please notice that you should use local variable and cannot move FTS wrapper inside expression like
var q = db.Notes.Where(n => n.NoteText.Contains(FtsInterceptor.Fts("john")));
I have found that the easiest way to implement this is to setup and configure full-text-search in SQL Server and then use a stored procedure. Pass your arguments to SQL, allow the DB to do its job and return either a complex object or map the results to an entity. You don't necessarily have to have dynamic SQL, but it may be optimal. For example, if you need paging, you could pass in PageNumber and PageSize on every request without the need for dynamic SQL. However, if the number of arguments fluctuates per query, it will be the optimal solution.
As the other guys mentioned, I would say start using Lucene.NET
Lucene has a pretty high learning curve, but I found an wrapper for it called "SimpleLucene", that can be found on CodePlex
Let me quote a couple of codeblocks from the blog to show you how easy it is to use. I've just started to use it, but got the hang of it really fast.
First, get some entities from your repository, or in your case, use Entity Framework
public class Repository
{
public IList<Product> Products {
get {
return new List<Product> {
new Product { Id = 1, Name = "Football" },
new Product { Id = 2, Name = "Coffee Cup"},
new Product { Id = 3, Name = "Nike Trainers"},
new Product { Id = 4, Name = "Apple iPod Nano"},
new Product { Id = 5, Name = "Asus eeePC"},
};
}
}
}
The next thing you want to do is create an index-definition
public class ProductIndexDefinition : IIndexDefinition<Product> {
public Document Convert(Product p) {
var document = new Document();
document.Add(new Field("id", p.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
document.Add(new Field("name", p.Name, Field.Store.YES, Field.Index.ANALYZED));
return document;
}
public Term GetIndex(Product p) {
return new Term("id", p.Id.ToString());
}
}
and create an search index for it.
var writer = new DirectoryIndexWriter(
new DirectoryInfo(#"c:\index"), true);
var service = new IndexService();
service.IndexEntities(writer, Repository().Products, ProductIndexDefinition());
So, you now have an search-able index. The only remaining thing to do is.., searching! You can do pretty amazing things, but it can be as easy as this: (for greater examples see the blog or the documentation on codeplex)
var searcher = new DirectoryIndexSearcher(
new DirectoryInfo(#"c:\index"), true);
var query = new TermQuery(new Term("name", "Football"));
var searchService = new SearchService();
Func<Document, ProductSearchResult> converter = (doc) => {
return new ProductSearchResult {
Id = int.Parse(doc.GetValues("id")[0]),
Name = doc.GetValues("name")[0]
};
};
IList<Product> results = searchService.SearchIndex(searcher, query, converter);
The example here http://www.entityframework.info/Home/FullTextSearch is not complete solution. You will need to look into understand how the full text search works. Imagine you have a search field and the user types 2 words to hit search. The above code will throw an exception. You need to do pre-processing on the search phrase first to pass it to the query by using logical AND or OR.
for example your search phrase is "blah blah2" then you need to convert this into:
var searchTerm = #"\"blah\" AND/OR \"blah2\" ";
Complete solution would be:
value = Regex.Replace(value, #"\s+", " "); //replace multiplespaces
value = Regex.Replace(value, #"[^a-zA-Z0-9 -]", "").Trim();//remove non-alphanumeric characters and trim spaces
if (value.Any(Char.IsWhiteSpace))
{
value = PreProcessSearchKey(value);
}
public static string PreProcessSearchKey(string searchKey)
{
var splitedKeyWords = searchKey.Split(null); //split from whitespaces
// string[] addDoubleQuotes = new string[splitedKeyWords.Length];
for (int j = 0; j < splitedKeyWords.Length; j++)
{
splitedKeyWords[j] = $"\"{splitedKeyWords[j]}\"";
}
return string.Join(" AND ", splitedKeyWords);
}
this methods uses AND logic operator. You might pass that as an argument and use the method for both AND or OR operators.
You must escape none-alphanumeric characters otherwise it would throw exception when a user enters alpha numeric characters and you have no server site model level validation in place.
I recently had a similar requirement and ended up writing an IQueryable extension specifically for Microsoft full text index access, its available here IQueryableFreeTextExtensions