Using Apache Lucene to search - c#

I've been trying to implement Lucene to make the searching on my website faster.
My code currently works, however, I think I am not correctly making use of Lucene. Right now, my search query is productName:asterisk(input)asterisk - I can't imagine this is what you're supposed to do to find all products where productName contains input. I think it has something to do with the way I save the fields to a document.
My code:
LuceneHelper.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity.Migrations.Model;
using System.Linq;
using System.Threading.Tasks;
using Lucene.Net;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Rentpro.Models;
using RentPro.Models.Tables;
using RentProModels.Models;
namespace RentPro.Helpers
{
public class LuceneHelper
{
private const Lucene.Net.Util.Version Version = Lucene.Net.Util.Version.LUCENE_30;
private bool IndicesInitialized;
private List<Language> Languages = new List<Language>();
public void BuildIndices(DB db)
{
Languages = GetLanguages(db);
Analyzer analyzer = new StandardAnalyzer(Version);
List<Product> allProducts = db.GetAllProducts(true, false);
foreach (Language l in Languages)
{
BuildIndicesForLanguage(allProducts, analyzer, l.ID);
}
IndicesInitialized = true;
}
private void BuildIndicesForLanguage(List<Product> products, Analyzer analyzer, int id = 0)
{
using (
IndexWriter indexWriter = new IndexWriter(GetDirectory(id), analyzer,
IndexWriter.MaxFieldLength.UNLIMITED))
{
var x = products.Count;
foreach (Product p in products)
{
SearchProduct product = SearchProduct.FromProduct(p, id);
Document document = new Document();
Field productIdField = new Field("productId", product.ID.ToString(), Field.Store.YES, Field.Index.NO);
Field productTitleField = new Field("productName", product.Name, Field.Store.YES, Field.Index.ANALYZED);
Field productDescriptionField = new Field("productDescription", product.Description, Field.Store.YES, Field.Index.ANALYZED);
Field productCategoryField = new Field("productCategory", product.Category, Field.Store.YES, Field.Index.ANALYZED);
Field productCategorySynonymField = new Field("productCategorySynonym", product.CategorySynonym, Field.Store.YES, Field.Index.ANALYZED);
Field productImageUrlField = new Field("productImageUrl", product.ImageUrl, Field.Store.YES, Field.Index.NO);
Field productTypeField = new Field("productType", product.Type, Field.Store.YES, Field.Index.NO);
Field productDescriptionShortField = new Field("productDescriptionShort", product.DescriptionShort, Field.Store.YES, Field.Index.NO);
Field productPriceField = new Field("productPrice", product.Price, Field.Store.YES, Field.Index.NO);
document.Add(productIdField);
document.Add(productTitleField);
document.Add(productDescriptionField);
document.Add(productCategoryField);
document.Add(productCategorySynonymField);
document.Add(productImageUrlField);
document.Add(productTypeField);
document.Add(productDescriptionShortField);
document.Add(productPriceField);
indexWriter.AddDocument(document);
}
indexWriter.Optimize();
indexWriter.Commit();
}
}
public List<SearchProduct> Search(string input)
{
if (!IndicesInitialized)
{
BuildIndices(new DB());
return Search(input);
}
IndexReader reader = IndexReader.Open(GetCurrentDirectory(), true);
Searcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer(Version);
TopScoreDocCollector collector = TopScoreDocCollector.Create(100, true);
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version,
new[] { "productDescription", "productCategory", "productCategorySynonym", "productName" }, analyzer)
{
AllowLeadingWildcard = true
};
searcher.Search(parser.Parse("*" + input + "*"), collector);
ScoreDoc[] hits = collector.TopDocs().ScoreDocs;
List<int> productIds = new List<int>();
List<SearchProduct> results = new List<SearchProduct>();
foreach (ScoreDoc scoreDoc in hits)
{
Document document = searcher.Doc(scoreDoc.Doc);
int productId = int.Parse(document.Get("productId"));
if (!productIds.Contains(productId))
{
productIds.Add(productId);
SearchProduct result = new SearchProduct
{
ID = productId,
Description = document.Get("productDescription"),
Name = document.Get("productName"),
Category = document.Get("productCategory"),
CategorySynonym = document.Get("productCategorySynonym"),
ImageUrl = document.Get("productImageUrl"),
Type = document.Get("productType"),
DescriptionShort = document.Get("productDescriptionShort"),
Price = document.Get("productPrice")
};
results.Add(result);
}
}
reader.Dispose();
searcher.Dispose();
analyzer.Dispose();
return results;
}
private string GetDirectoryPath(int languageId = 1)
{
return GetDirectoryPath(Languages.SingleOrDefault(x => x.ID == languageId).UriPart);
}
private string GetDirectoryPath(string languageUri)
{
return AppDomain.CurrentDomain.BaseDirectory + #"\App_Data\LuceneIndices\" + languageUri;
}
private List<Language> GetLanguages(DB db)
{
return db.Languages.ToList();
}
private int GetCurrentLanguageId()
{
return Translator.GetCurrentLanguageID();
}
private FSDirectory GetCurrentDirectory()
{
return FSDirectory.Open(GetDirectoryPath(GetCurrentLanguageId()));
}
private FSDirectory GetDirectory(int languageId)
{
return FSDirectory.Open(GetDirectoryPath(languageId));
}
}
public class SearchProduct
{
public int ID { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string Type { get; set; }
public string DescriptionShort { get; set; }
public string Price { get; set; }
public string Category { get; set; }
public string CategorySynonym { get; set; }
public static SearchProduct FromProduct(Product p, int languageId)
{
return new SearchProduct()
{
ID = p.ID,
Description = p.GetText(languageId, ProductLanguageType.Description),
Name = p.GetText(languageId),
ImageUrl =
p.Images.Count > 0
? "/Company/" + Settings.Get("FolderName") + "/Pictures/Products/100x100/" +
p.Images.Single(x => x.Type == "Main").Url
: "",
Type = p is HuurProduct ? "HuurProduct" : "KoopProduct",
DescriptionShort = p.GetText(languageId, ProductLanguageType.DescriptionShort),
Price = p is HuurProduct ? ((HuurProduct)p).CalculatedPrice(1, !Settings.GetBool("BTWExLeading")).ToString("0.00") : "",
Category = p.Category.Name,
CategorySynonym = p.Category.Synonym
};
}
}
}
How I call the LuceneHelper:
public ActionResult Lucene(string SearchString, string SearchOrderBy, int? page, int? amount)
{
List<SearchProduct> searchResults = new List<SearchProduct>();
if (!SearchString.IsNullOrWhiteSpace())
{
LuceneHelper lucene = new LuceneHelper();
searchResults = lucene.Search(SearchString);
}
return View(new LuceneSearchResultsVM(db, SearchString, searchResults, SearchOrderBy, page ?? 1, amount ?? 10));
}
LuceneSearchResultsVM:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using RentPro.Models.Tables;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Ajax.Utilities;
using Rentpro.Models;
using RentPro.Helpers;
using RentProModels.Models;
namespace RentPro.ViewModels
{
public class LuceneSearchResultsVM
{
public List<SearchProduct> SearchProducts { get; set; }
public bool BTWActive { get; set; }
public bool BTWEXInput { get; set; }
public bool BTWShow { get; set; }
public bool BTWExLeading { get; set; }
public string FolderName { get; set; }
public string CurrentSearchString { get; set; }
public string SearchOrderBy { get; set; }
public int Page;
public int Amount;
public String SearchQueryString {
get
{
return Translator.Translate("Zoekresultaten voor") + ": " + CurrentSearchString + " (" +
SearchProducts.Count + " " + Translator.Translate("resultaten") + " - " +
Translator.Translate("pagina") + " " + Page + " " + Translator.Translate("van") + " " +
CalculateAmountOfPages() + ")";
}
set { }
}
public LuceneSearchResultsVM(DB db, string queryString, List<SearchProduct> results, string searchOrderBy, int page, int amt)
{
BTWActive = Settings.GetBool("BTWActive");
BTWEXInput = Settings.GetBool("BTWEXInput");
BTWShow = Settings.GetBool("BTWShow");
BTWExLeading = Settings.GetBool("BTWExLeading");
FolderName = Settings.Get("FolderName");
SearchProducts = results;
CurrentSearchString = queryString;
if (searchOrderBy.IsNullOrWhiteSpace())
{
searchOrderBy = "Name";
}
SearchOrderBy = searchOrderBy;
Amount = amt == 0 ? 10 : amt;
int maxPages = CalculateAmountOfPages();
Page = page > maxPages ? maxPages : page;
SearchLog.MakeEntry(queryString, SearchProducts.Count(), db, HttpContext.Current.Request.UserHostAddress);
}
public List<SearchProduct> GetOrderedList()
{
List<SearchProduct> copySearchProductList = new List<SearchProduct>(SearchProducts);
copySearchProductList = copySearchProductList.Skip((Page - 1) * Amount).Take(Amount).ToList();
switch (SearchOrderBy)
{
case "Price":
copySearchProductList.Sort(new PriceSorter());
break;
case "DateCreated":
return copySearchProductList; //TODO
default:
return copySearchProductList.OrderBy(n => n.Name).ToList();
}
return copySearchProductList;
}
public int CalculateAmountOfPages()
{
int items = SearchProducts.Count;
return items / Amount + (items % Amount > 0 ? 1 : 0);
}
}
public class PriceSorter : IComparer<SearchProduct>
{
public int Compare(SearchProduct x, SearchProduct y)
{
if (x == null || x.Price == "") return 1;
if (y == null || y.Price == "") return -1;
decimal priceX = decimal.Parse(x.Price);
decimal priceY = decimal.Parse(y.Price);
return priceX > priceY ? 1 : priceX == priceY ? 0 : -1;
}
}
}
Any help would be greatly appreciated.
Example input list of products:
Query:
SELECT Product.ID, Product.Decription, Product.Name FROM Product
Desired results:
SQL Server query equivalent:
SELECT Product.ID, Product.Decription, Product.Name FROM Product WHERE Product.Name LIKE '%Zelf%' OR Product.Decription LIKE '%Zelf%'
Basically, Zelf is the input. I want to find all matches with product descriptions or product names that contain the input string.

ucene not allows to use ? or * as starting symbols of the searching term. To overcome this issue you need to store in your index a sub-strings from any position of word to it end position. E.g. for word test you should put to index
test
est
st
t
I recommend to use separate field for that. Java example for case if you have a short field with one word like a product name.
for(int i = 0; i < product.SafeName.length()-1; i++){
Field productTitleSearchField = new Field("productNameSearch", product.SafeName.substring(i, product.SafeName.length()), Field.Store.NO, Field.Index.ANALYZED);
}
After this you can use following query string
productNameSearch:(input)asterisk or use a PrefixQuery for searching product names containing input.
In case if you have several words in you field and for you will be enough to have some reasonable length of your input, then it will better to add for this field a NGramTokenFilter. You if have limit on your input string from n to m you should create a NGram Token Filter with n minGram and m maxGramm. If you has word test and you limit 2 to 3 you will have in your index words
te
tes
es
est
st
After this you can search via string
ngrammField:(input)

This doesn't answer your question but it is safer to use the using block in C#. In your current code, calling dispose can throw.
You're doing:
IndexReader reader = IndexReader.Open(GetCurrentDirectory(), true);
Searcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer(Version);
//...
reader.Dispose();
searcher.Dispose();
analyzer.Dispose();
Which can be replaced with:
using (IndexReader reader = IndexReader.Open(GetCurrentDirectory(), true))
using (Searcher searcher = new IndexSearcher(reader))
using (Analyzer analyzer = new StandardAnalyzer(Version))
{
//Do whatever else here.. No need to call "dispose".
}
The above is pretty much a try -> finally statement where it tries to do whatever is in the using statement. If anything throws, the finally block disposes the resources opened/allocated.
Another way (comma operator.. if all variables are of the same type) is:
using (whatever foo = new whatever(), whatever bar = new whatever(), ...)
{
//do whatever here..
}

Related

Trying to properly set up query for match of 2 csv files got stuck

Here's an example of what the data looks like on each csv.
inventory.csv
ID, payment, Receipt#
90006, VISA, jk73kl_
90006, VISA, null
inventory.csv
INFO, VIEWS, DATE
9006_Produce_Banana_jk73kl__, 0, 10-13-20
9006_Produce_Banana, 0, 10-13-20
I am having trouble with my where, I need to search both forms and if there is a matching receipt number pull them out and combine the two rows.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
string[] ourDataSheet = System.IO.File.ReadAllLines(#"../../OurData.csv");
string[] theirDataSheet = System.IO.File.ReadAllLines(#"../../TheirData.csv");
string ourDataHeaders = ourDataSheet[0];
string theirDataHeaders = theirDataSheet[0];
IEnumerable<string> TrackingQuery =
from ourData in ourDataSheet
let ourDataFields = ourData.Split(',')
from theirData in theirDataSheet
let theirDataFields = theirData.Split(',')
where theirDataFields[0].EndsWith(ourDataFields[2])
select ourDataFields[0] + "," + ourDataFields[1] + "," + ourDataFields[2] + "," + theirDataFields[0] + "," + theirDataFields[0] + "," + theirDataFields[1] + "," + theirDataFields[2] + "," + theirDataFields[3];
OutPutResults(TrackingQuery);
Console.ReadKey();
}
static void OutPutResults(IEnumerable<string> query)
{
foreach(string item in query)
{
Console.WriteLine(item);
Console.Read();
}
}
}
}
First things first, I would recommend that you use a third-party package like CsvHelper and do something like the following
public class Sale
{
public int ID { get; set; }
public string Payment { get; set; }
[Name("Recipt#")]
public string Recipt { get; set; }
}
public class Inventory
{
public string INFO { get; set; }
public string VIEWS { get; set; }
public string DATE { get; set; }
}
IEnumerable<Sale> sales;
IEnumerable<Inventory> inventory;
using (var reader = new StreamReader(#"../../OurData.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
sales = csv.GetRecords<Sale>();
}
using (var reader = new StreamReader(#"../../TheirData.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
inventory = csv.GetRecords<Inventory>();
}
var results = sales.Where(s => inventory.Any(i => i.INFO.EndsWith(s.Recipt)));

Read a XML with Linq C# using where condition

I try to make a little Service for my business but it doesn't works.
<item>
<key>12323</key>
<summary></summary>
<reporter username="12313asdf">1232 asdf iii</reporter>
<cusomfields>
<customfield id="customfield_37723" key="xyz">
<customfieldname>First Name</customfieldname>
<customfieldvalues>
<customfieldvalue>Klaus</customfieldvalue>
</customfieldvalues>
</customfield>
//...many customfields
</customfields>
</item>
I created a c# method with this code -> but it doesn't work :(
XDocument doc = XDocument.Load(fileName);
var obj = (from c in doc.Descendants("item")
select new ServiceRequest_NewUser()
{
TicketID = c.Element("key").Value,
Summary = c.Element("summary").Value,
ReporterNT = c.Element("reporter").Attribute("username").Value,
ReporterFull = c.Element("reporter").Value,
FirstName = (from f in c.Descendants("customfields")
where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
}).ToList();
foreach (var i in obj)
{
var test = i.FirstName;
Console.WriteLine($"{i.TicketID} {i.Summary} {i.ReporterNT} {i.ReporterFull} {i.FirstName}");
}
Where is my fault? I did a alternative version of code in the comment tag. I need to output the value "Klaus".
I thank you in advance for the help.
If you expected to see Klaus in the FirstName, you should write this:
var obj = (from c in doc.Elements("item")
select new
{
TicketID = c.Element("key")?.Value,
Summary = c.Element("summary")?.Value,
ReporterNT = c.Element("reporter")?.Attribute("username")?.Value,
ReporterFull = c.Element("reporter").Value,
FirstName = (from f in c.Descendants("customfields")
where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
}).ToList();
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Item> items = doc.Descendants("item").Select(x => new Item()
{
key = (string)x.Element("key"),
summary = (string)x.Element("summary"),
usernameText = (string)x.Element("reporter"),
username = (string)x.Element("reporter").Attribute("username"),
fields = x.Descendants("customfield").Select(y => new Field()
{
id = (string)y.Attribute("id"),
key = (string)y.Attribute("key"),
name = (string)y.Element("customfieldname"),
values = y.Descendants("customfieldvalue").Select(z => (string)z).ToList()
}).ToList()
}).ToList();
List<Item> customfield_37723 = items.Where(x => x.fields.Any(y => y.id == "customfield_37723")).ToList();
foreach (Item item in customfield_37723)
{
Console.WriteLine("Item : key = '{0}', summary = '{1}', username Text = '{2}', username = '{3}'",
item.key, item.summary, item.usernameText, item.username);
foreach (Field field in item.fields)
{
Console.WriteLine(" Field : id = '{0}', key = '{1}', name = '{2}', values = '{3}'",
field.id, field.key, field.name, string.Join(",", field.values));
}
}
Console.ReadLine();
}
}
public class Item
{
public string key { get; set; }
public string summary { get; set; }
public string usernameText { get; set; }
public string username { get; set; }
public List<Field> fields { get; set; }
}
public class Field
{
public string id { get; set; }
public string key { get; set; }
public string name { get; set; }
public List<string> values { get; set; }
}
}

How to perform a LINQ where clause with a dynamic column

I am attempting to use System.Linq.Dynamic.Core (https://github.com/StefH/System.Linq.Dynamic.Core) in order to create dynamic queries.
Following the example given on the github page, I have tried the following
lstContacts = lstContacts.Where("#0 == true", "active");
However I get the following result:
'active is not a valid value for Boolean
Reference this library:
using System.Linq.Dynamic;
And make your query like that:
string columnName = "active";
var lstContacts = lstContacts.Where(columnName + " == true");
Here is a working example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
public class Program
{
public static void Main()
{
var lstContacts = new List<Contact>{
new Contact{Id = 1, Active = true, Name = "Chris"},
new Contact{Id = 2, Active = true, Name = "Scott"},
new Contact{Id = 3, Active = true, Name = "Mark"},
new Contact{Id = 4, Active = false, Name = "Alan"}};
string columnName = "Active";
List<Contact> results = lstContacts.Where(String.Format("{0} == true", columnName)).ToList();
foreach (var item in results)
{
Console.WriteLine(item.Id.ToString() + " - " + item.Name.ToString());
}
}
}
public class Contact
{
public int Id
{
get;
set;
}
public bool Active
{
get;
set;
}
public string Name
{
get;
set;
}
}
You can experiment with this .net-fiddle-here

datarow filtering array with dataset c# asp net

I have this page of operators that has two tables with data from database, one table with existing operators and one table with existing users. If a user is already an operator, I want that row to be hidden in the table. Here is my code:
C#:
var userDetailsList = new List<ContactPartial>();
TellusAPI.TellusUserDetails userDetails;
var operators = _administrationSystem.GetOperatorsInformation(userId); //DataSet
var getUser = webSearch.DoSearchForNameAndNumber(userId, txtSearchForOperator.Text, false, "", "", false, false, out userDetails); //Array
if (getUser == null)
{
userDetailsList.Add(new ContactPartial(userDetails));
rptAdd.DataSource = null;
}
else
{
userDetailsList = getUser.Select(x => new ContactPartial(x)).ToList();
var dv = new DataView(operators.Tables[0]);
foreach (var Operator in userDetailsList)
{
if (!userDetailsList.Contains(Operator)) continue;
dv.RowFilter = "ID = " + Operator.Id;
}
rptAdd.DataSource = userDetailsList; //Repeater
}
Class:
/// <summary>
/// Class for converting.
/// </summary>
public class ContactPartial
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Email { get; set; }
public ContactPartial(TellusUserDetails tud)
{
if (tud == null)
{
return;
}
Id = tud.UserID;
FirstName = tud.FirstName;
LastName = tud.LastName;
CompanyName = tud.Organisation.Description;
Email = tud.Email;
}
public ContactPartial(TellusSearchUserInfo tsi)
{
if (tsi == null)
{
return;
}
Id = tsi.ID;
FirstName = tsi.FirstName;
LastName = tsi.LastName;
CompanyName = tsi.CompanyName;
Email = tsi.Email;
}
}
So I now compare these two and filter the rows with ID, but it still reads all rows.
foreach (var Operator in userDetailsList) ******
{
if (!userDetailsList.Contains(Operator)) continue;
dv.RowFilter = "ID = " + Operator.Id;
}
I see some problem with naming convention .. You should corretly notify what is operator and what is user details object. Don't mix them up.
foreach (var user in userDetailsList)
{
// Since dv is the one which contain operator details
if (dv.Select("ID= '" + user.Id + "'").Count > 0)
{
dv.RowFilter = "ID = " + user.Id;
}
}

The specified table does not exist[entity]

I have spent hours trying to figure out why my database cannot find the table I have found numerous examples and none have seemed to help. I have created a separate class to handle the database operations so I can use it on multiple pages.
Here is the code
[Table]
public class MatchItem
{
[Column(IsPrimaryKey = true, CanBeNull=false,IsDbGenerated=true)]
public int MatchID { get; set; }
[Column(CanBeNull = false)]
public string MatchNumber { get; set; }
[Column(CanBeNull = false)]
public string EventName { get; set; }
[Column(CanBeNull = false)]
public DateTime Time { get; set; }
[Column(CanBeNull = false)]
public string[] RedTeams { get; set; }
[Column(CanBeNull = false)]
public string[] BlueTeams { get; set; }
[Column(CanBeNull = false)]
public int RedFinal { get; set; }
[Column(CanBeNull = false)]
public int BlueFinal{ get; set; }
}
Here is the Data context
public class MatchDataContext:DataContext
{
public MatchDataContext(string connectionString) :
base(connectionString)
{
}
public Table<MatchItem> Matches
{
get
{
return this.GetTable<MatchItem>();
}
}
}
I made a class so I could use it on multiple pages
public class MatchDBManager
{
private static string connectionString = #"Data Source=isostore:/DB.sdf";
public MatchDBManager()
{
initialize();
}
public void initialize()
{
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
if (Mchdb.DatabaseExists())
{
Console.WriteLine("DB already exists");
}
else
{
Mchdb.CreateDatabase();
Console.WriteLine("DB created");
}
}
}
public void addMatchData(IList<MatchItem> data)
{
//this.clearData();
//initialize();
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
Mchdb.Matches.InsertAllOnSubmit(data);
Mchdb.SubmitChanges();
}
}
public IList<MatchItem> getTeamData(string teamNum)
{
IList<MatchItem> MatchList = null;
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
IQueryable<MatchItem> mchQuery = from mch in Mchdb.Matches where (mch.RedTeams[0] == teamNum || mch.RedTeams[1] == teamNum || mch.RedTeams[2] == teamNum || mch.BlueTeams[0] == teamNum || mch.BlueTeams[1] == teamNum || mch.BlueTeams[2] == teamNum) select mch;
MatchList = mchQuery.ToList();
}
return MatchList;
}
public IList<MatchItem> getEventData(string eventID)
{
IList<MatchItem> MatchList = null;
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
IQueryable<MatchItem> mchQuery = from mch in Mchdb.Matches where mch.Event == eventID select mch;
MatchList = mchQuery.ToList();
}
return MatchList;
}
private void clearData()
{
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
if (Mchdb.DatabaseExists())
{
Mchdb.DeleteDatabase();
}
}
}
}
I have the error The specified table does not exist[Match].
Added here is where I download
public IList<MatchItem> ParseXML(XmlReader reader)
{
//List<string> save = new List<string>();
List<MatchItem> MatchList= new List<MatchItem>();
XElement matchData;
matchData = XElement.Load(reader);
StringBuilder output = new StringBuilder();
int count = 0;
var matches = from item
in matchData.Elements("match")
select item;
foreach (XElement eachmatch in matches)
{
MatchItem mch = new MatchItem();
string Time = ((eachmatch.Element("pubdate").Value).ToString());
mch.EventName = ((eachmatch.Element("event").Value).ToString());
mch.MatchNumber = ((eachmatch.Element("mch").Value).ToString() + (eachmatch.Element("typ").Value).ToString());
string[] RT = { eachmatch.Element("red1").Value.ToString(), eachmatch.Element("red2").Value.ToString(), eachmatch.Element("red3").Value.ToString() };
string[] BT = { eachmatch.Element("blue1").Value.ToString(), eachmatch.Element("blue2").Value.ToString(), eachmatch.Element("blue3").Value.ToString() };
string RF = ((eachmatch.Element("rfin").Value).ToString());
string BF = ((eachmatch.Element("bfin").Value).ToString());
// Time = Time.Substring(0, (Time.IndexOf("+") - 1));
mch.Time = DateTime.Parse(Time);
mch.RedTeams = RT;
mch.BlueTeams = BT;
mch.RedFinal = int.Parse(RF);
mch.BlueFinal= int.Parse(BF);
mch.MatchID = count;
count += 1;
MatchList.Add(mch);
}
return MatchList;
}
This is where I call this method
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
initializeDB();
if (e.Error == null)
{
XmlReader reader = XmlReader.Create(new StringReader(e.Result));
DownloadInfo di = new DownloadInfo();
IList <MatchItem>data= di.ParseXML(reader);
outputer(data);
addData(data.ToList<MatchItem>());
}
else
{
IList<MatchItem> data = getTeamData(strMyTeam);
outputer(data);
}
}
I ended up removing the DatabaseManager class and putting the functions in the main code
Then I output them to the screen here
public void outputer(IList<MatchItem> mch)
{
for (int i = 0; i < mch.Count; i++)
{
Score sc = new Score();
sc.Width = lsbData.Width;
sc.Height = sc.Height;
sc.Time = mch[i].Time.ToString();
sc.Event = mch[i].EventName;
sc.RT = mch[i].RedTeams[0] + " " + mch[i].RedTeams[1] + " " + mch[i].RedTeams[2];
sc.BT = mch[i].BlueTeams[0] + " " + mch[i].BlueTeams[1] + " " + mch[i].BlueTeams[2];
sc.RF = mch[i].RedFinal.ToString();
sc.BF = mch[i].BlueFinal.ToString();
lsbData.Items.Add(sc);
}
}
*note:score is a custom control that works(and worked) before the database code *
I don't see where you actually create a Match Object.
if you have you need to include that code in the question as well. and if you haven't, that would explain why it doesn't exist.
Addition
in order to add Match Objects to a list you will have to create the objects first then add them to the list, I don't think you can create the whole list of objects before creating each individual object.
more Additional Information
the object still needs to be created before you can add items to it. that is what the error is telling you. you don't have the object to insert data into.
Match Table1 = new Match();
this creates a new Match object which allows you to access the pieces of the object and insert data into the object like this
Table1.MatchNumber = 42
you can't add to something to a memory location until you set aside that memory location for that specific person and give it a name.
when you create that class you can add functions and all sorts of fun stuff to it, but you can't use any of it until you have created a Match Object.
you can't add something to a list that doesn't exist, you have to create the Match Object first, then add it to the list

Categories

Resources