How can I loop over Tables which contain specific characters in their AOT name and delete the data? - x++

I want to loop over a few tables where the name (aotName) begins with 'HbcCka', finally I want to delete all data from the tables.
Now I need a logic to empty the tables. How can I achieve this?
UPDATED:
static void tstDeleteForecastingData(Args _args)
{
Dictionary dictionary = new Dictionary();
int i;
SysDictTable dictTable;
;
for (i=1 ; i<=dictionary.tableCnt() ; i++)
{
if (strScan(tableid2name(dictionary.tableCnt2Id(i)), "HbcCka", 1, strLen(dictionary.tableName(i))))
{
info(strfmt('%1;%2', dictionary.tableCnt2Id(i), tableid2name( dictionary.tableCnt2Id(i) )));
}
}
}

Truncate the tables in all companies?
Use System Administration\Periodic\Databases\SQL Administration, mark the tables then choose Table actions\Truncate.
Or make a class with a server main method:
ClassDeclaration tstDeleteForecastingData
{
}
static server void main(Args _args)
{
Dictionary dictionary = new Dictionary();
int i;
for (i=1 ; i<=dictionary.tableCnt() ; i++)
{
if (strScan(tableid2name(dictionary.tableCnt2Id(i)), "HbcCka", 1, 99)))
{
info(strfmt('%1;%2', dictionary.tableCnt2Id(i), tableid2name( dictionary.tableCnt2Id(i) )));
new SqlDataDictionaryPermission(methodstr(SqlDataDictionary, tableTruncate)).assert();
new SqlDataDictionary().tableTruncate(dictionary.tableCnt2Id(i), false);
CodeAccessPermission::revertAssert();
}
}
}
If only in current company:
Common table = new DictTable(<tableId>).makeRecord();
table.skipDeleteMethod(true);
table.skipDeleteAction(true);
delete_from table;

To speed things up, you could use the stored procedure sp_msforeachtable to loop tables in the database (with a check on the table names) and just write your delete statement to delete records where the dataAreaId is the one you want.
Something like this can be use to delete the tables starting with HbcCka in the CEU company:
exec sp_msforeachtable '
if "?" like "HbcCka%"
delete from ? where DataAreaId = "CEU"
'

Related

how to execute SQL code separatly in SqlServerMigrationSqlGenerator Generates method?

I want to run an SQL script after each new table created through Entity Framework.
I created an override for 'CreateTableOperation' like this:
protected override void Generate(CreateTableOperation createTableOperation)
{
string tenantID = "tenantID";
base.Generate(createTableOperation);
//If the table contain the column "tenantID",
if ((from x in createTableOperation.Columns
where x.Name == tenantID
select x).Any()
)
{
//Add the Security Policies for this table
using (var writer = Writer())
{
writer.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy ");
//Note: dbo. is already part of the .Name, don't add it manually before .Name
writer.WriteLine($"ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([{tenantID}]) ON [{createTableOperation.Name}], ");
writer.WriteLine($"ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([{tenantID}]) ON [{createTableOperation.Name}] ");
Statement(writer);
}
}
}
Let's say I create a new class 'TEST'.
The problem is when I run my Update-Database in the Package Manager Console, the SQL is executed in one big block and create an error because the table is not yet created and I'm trying to get the table.name Package Manager result after Update-Database:
CREATE TABLE [dbo].[TEST] (
[ID] [int] NOT NULL IDENTITY,
[NameTEST] [nvarchar](max),
[TenantID] [int] NOT NULL,
CONSTRAINT [PK_dbo.TEST] PRIMARY KEY ([ID])
)
ALTER SECURITY POLICY rls.tenantAccessPolicy
ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([tenantID]) ON [dbo.TEST],
ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([tenantID]) ON [dbo.TEST]
Cannot find the object "dbo.TEST" because it does not exist or you do not have permissions.
Is there a way to break between the base.Generate(createTableOperation); and my Statement(writer);? (I already tried multiple things with 'GO' without much success). Or is it that I'm not supposed to put code in that method?
I couldn't find a solution/documentation to separate the code/batch SQL in Generate(CreateTableOperation createTableOperation).
What I did instead was to
generate dynamic SQL scripts in the Generate(CreateTableOperation createTableOperation) method
/// <summary>
/// Generate dynamically named .sql file for CREATE and DROP Security Policies (Row-Level Security (Company can't see/insert data of another company))
/// </summary>
/// <param name="createTableOperation">Default parameter that comes with the override method.</param>
protected override void Generate(CreateTableOperation createTableOperation)
{
base.Generate(createTableOperation);
string fullFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\SecurityPolicies");
//Remove the schema for the dynamic creation of the .sql filename else it throw an exception:
int indexOfDot = createTableOperation.Name.IndexOf(".");
indexOfDot++; //Because it's 0 base, add 1 char
string tableNameWithoutSchema = (indexOfDot < 0) ? createTableOperation.Name : createTableOperation.Name.Remove(0, indexOfDot);
string filePathCreate = Path.Combine(fullFolderPath, $"CreateSecurityPolicies_{tableNameWithoutSchema}.sql");
string filePathDrop = Path.Combine(fullFolderPath, $"DropSecurityPolicies_{tableNameWithoutSchema}.sql");
//If .sql files doesn't exists, create them
if (!File.Exists(filePathCreate))
{
using (StreamWriter sw = new StreamWriter(filePathCreate, true))
{
sw.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy");
//Note: Don't concatenate 'dbo.{}' because 'createTableOperation.Name' already include 'dbo'
sw.WriteLine($" ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON {createTableOperation.Name},");
sw.WriteLine($" ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON {createTableOperation.Name}");
sw.WriteLine("GO");
sw.Close();
}
}
if (!File.Exists(filePathDrop))
{
using (StreamWriter sw = new StreamWriter(filePathDrop, true))
{
sw.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy");
sw.WriteLine($" DROP FILTER PREDICATE ON {createTableOperation.Name},");
sw.WriteLine($" DROP BLOCK PREDICATE ON {createTableOperation.Name}");
sw.WriteLine("GO");
sw.Close();
}
}
}
Then, with my SQL scripts in a folder, add it manually to my solution.
Add-Migration just to run my SQL script by adding code into the empty (up-to-date) migration class.
public override void Up()
{
string sqlFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\CreateSecurityPolicies_Client.sql");
string sqlText = System.IO.File.ReadAllText(sqlFilePath);
Sql(sqlText);
}
public override void Down()
{
string sqlFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\DropSecurityPolicies_Client.sql");
string sqlText = System.IO.File.ReadAllText(sqlFilePath);
Sql(sqlText);
}
This is the best I can come up with for the moment. I hope it can helps other EntityFramework programmers!

Mahout Recomendaton engine recommending products and with its Quantity to customer

i am working on mahout recommendation engine use case.I precomputed recommendations and stored in database. now i am planning to expose with taste rest services to .net.i had limited customers and products.it is distributor level recommendation use case.my question is if new distributor comes in ,how would i suggests recommendations to him.and also how would i suggest the Quantity of Recommended product to each distributor.could you people give me some guidance.am i going to face performance issues..?
One way is, when new user comes, to precompute the recommendations from scratch for all the users or only for this user. You should know that this user might change the recommendations for the others too. Its up to your needs frequently do you want to do the pre-computations.
However, if you have limited number of users and items, another way is to have online recommender that computes the recommendations in real time. If you use the FileDataModel, there is a way to get the data from the new user periodically (See the book Mahout in Action). If you use in memory data model, which is faster, you can override the methods: setPreference(long userID, long itemID, float value) and removePreference(long userID, long itemID), and whenever new user comes and likes or removes some items you should call these methods on your data model.
EDIT: Basically you can get the GenericDataModel, and add this to the methods setPreference and removePreference. This will be your lower level data model. You can wrap it afterwards with ReloadFromJDBCDataModel by setting your data model in the reload() method like this:
DataModel newDelegateInMemory =
delegate.hasPreferenceValues()
? new MutableDataModel(delegate.exportWithPrefs())
: new MutableBooleanPrefDataModel(delegate.exportWithIDsOnly());
The overridden methods:
#Override
public void setPreference(long userID, long itemID, float value) {
userIDs.add(userID);
itemIDs.add(itemID);
setMinPreference(Math.min(getMinPreference(), value));
setMaxPreference(Math.max(getMaxPreference(), value));
Preference p = new GenericPreference(userID, itemID, value);
// User preferences
GenericUserPreferenceArray newUPref;
int existingPosition = -1;
if (preferenceFromUsers.containsKey(userID)) {
PreferenceArray oldPref = preferenceFromUsers.get(userID);
newUPref = new GenericUserPreferenceArray(oldPref.length() + 1);
for (int i = 0; i < oldPref.length(); i++) {
//If the item does not exist in the liked user items, add it!
if(oldPref.get(i).getItemID()!=itemID){
newUPref.set(i, oldPref.get(i));
}else{
//Otherwise remember the position
existingPosition = i;
}
}
if(existingPosition>-1){
//And change the preference value
oldPref.set(existingPosition, p);
}else{
newUPref.set(oldPref.length(), p);
}
} else {
newUPref = new GenericUserPreferenceArray(1);
newUPref.set(0, p);
}
if(existingPosition == -1){
preferenceFromUsers.put(userID, newUPref);
}
// Item preferences
GenericItemPreferenceArray newIPref;
existingPosition = -1;
if (preferenceForItems.containsKey(itemID)) {
PreferenceArray oldPref = preferenceForItems.get(itemID);
newIPref = new GenericItemPreferenceArray(oldPref.length() + 1);
for (int i = 0; i < oldPref.length(); i++) {
if(oldPref.get(i).getUserID()!=userID){
newIPref.set(i, oldPref.get(i));
}else{
existingPosition = i;
}
}
if(existingPosition>-1){
oldPref.set(existingPosition, p);
}else{
newIPref.set(oldPref.length(), p);
}
} else {
newIPref = new GenericItemPreferenceArray(1);
newIPref.set(0, p);
}
if(existingPosition == -1){
preferenceForItems.put(itemID, newIPref);
}
}
#Override
public void removePreference(long userID, long itemID) {
// User preferences
if (preferenceFromUsers.containsKey(userID)) {
List<Preference> newPu = new ArrayList<Preference>();
for (Preference p : preferenceFromUsers.get(userID)) {
if(p.getItemID()!=itemID){
newPu.add(p);
}
}
preferenceFromUsers.remove(userID);
preferenceFromUsers.put(userID, new GenericUserPreferenceArray(newPu));
}
if(preferenceFromUsers.get(userID).length()==0){
preferenceFromUsers.remove(userID);
userIDs.remove(userID);
}
if (preferenceForItems.containsKey(itemID)) {
List<Preference> newPi = new ArrayList<Preference>();
for (Preference p : preferenceForItems.get(itemID)) {
if(p.getUserID() != userID){
newPi.add(p);
}
}
preferenceForItems.remove(itemID);
preferenceForItems.put(itemID, new GenericItemPreferenceArray(newPi));
}
if(preferenceForItems.get(itemID).length()==0){
//Not sure if this is needed, but it works without removing the item
//preferenceForItems.remove(itemID);
//itemIDs.remove(itemID);
}
}
If by "new distributor" you mean that you have no data for them, no historical data. Then you cannot make recommendations using Mahout's recommenders.
You can suggest other items once they chose one. Use Mahout's "itemsimilarity" driver to calculate similar items for everything in your catalog. Then if they choose something you can suggest similar items.
The items that come from the itemsimilarity driver can be stored in you DB as a column value containing ids for similar items for every item. Then you can index the column with a search engine and use the user's first order as the query. This will return realtime personalized recommendations and is the most up-to-date method suggested by the Mahout people.
See a description of how to do this in this book by Ted Dunning, one of the leading Mahout Data Scientists. http://www.mapr.com/practical-machine-learning

How to get all values in a column in table using vaadin SQLContainer

Hi Stackoverflow members,
I have one SQLContainer with TableQuery. Now, I want to get all the values in one column. How can I get it? Or Shall I need to go with FreefromQuery?
This is my SQLContainer code
public SQLContainer getMyContainer() {
//FreeformQuery query = null;
SQLContainer container = null;
try {
connectionPool = new SimpleJDBCConnectionPool(
"com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/vaadin", "root", "root",
2, 5);
TableQuery query = new TableQuery("components", connectionPool);
/*query = new FreeformQuery(
"SELECT rowNum, colNum, caption, cType FROM items where screenId='"
+ screenName+"'", connectionPool);
query.setDelegate(new DemoFreeformQueryDelegate());*/
container = new SQLContainer(query);
} catch (Exception e) {
}
return container;
}
It depends on what you wish to do.
With SQLContainer you could do it this way:
// Returns a list with all ID's (Beware of large resultsets)
Collection<?> itemIDS= conatiner.getItemIds();
for (Object itemID : itemIDS)
{
Property property= container.getContainerProperty(itemID, "COLUMN");
Object data= property.getValue();
}
The getItemIds() must fetch all rows from the DB (at least the primary keys),
so this will cause troubles with large resultsets/tables.
https://vaadin.com/api/com/vaadin/data/util/sqlcontainer/SQLContainer.html#getItemIds%28%29

delete an object stored in several ArrayCollections

I have several arraycollections (I don't know their number in advance) which contain one same object (among others).
var obj:MyObject = new MyObject();
var arc1:ArrayCollection = new ArrayCollection();
arc1.addItem(obj)
// same operation for my x arraycollections
Is it possible to delete my object "obj" in the first arraycollection and automatically delete it in all other arraycollections too without deleting it in each arraycollection one by one?
Assuming that all your array collections share a common source, I would create ListCollectionViews instead of ArrayCollections and have them all point to a single ArrayCollection, i.e:
var masterCollection:ArrayCollection = new ArrayCollection();
for (var i:uint = 0; i < N; i++)
{
slaveCollections[i] = new ListCollectionView(masterCollection);
}
Whenever you add or remove an item from any slaveCollection it will be added/removed from the master and all your other lists will be updated via the CollectionEvent.
Assuming that all your array collections do NOT share a common source, I would add a collection event listener to each collection to handle your requirement:
for (var i:uint = 0; i < N; i++)
{
slaveCollections[i] = new ArrayCollection();
slaveCollections[i].addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionListener);
}
...
private function collectionListener(event:CollectionEvent):void
{
if (event.kind != CollectionEventKind.REMOVE)
return
for each(var slaveCollection:ArrayCollection in slaveCollections)
{
for each(var item:Object in event.items)
{
var itemIndex:int = slaveCollection.getItemIndex(item);
if (itemIndex >= 0)
{
slaveCollection.removeItemAt(itemIndex);
}
}
}
}
This should allow you to call: collection.removeItem(x) on any of your collections and have that item removed from the other ones.

Entity Framework Code First lazy loading non navigation properties

I'm using the entity framework code first CTP4.
Is it possible to lazy load non navigation properties like you can in NH 3.
A common example would be having a table containing a binary column. I only want to retrieve this column's data when I explicitly ask for that property in my code e.g. image.ImageData
Thanks
Ben
Vote here
Vote here
Read this
Ugly workaround:
public static void Main()
{
IEnumerable<MyTable> table;
using (Entities context = new Entities())
{
var buffer =
context.MyTable
.Select(myTable => new
{
Id = myTable.Id,
OtherColumn = myTable.OtherColumn
})
.ToArray();
table = buffer
.Select(t => new MyTable
{
Id = t.Id,
OtherColumn = t.OtherColumn
});
}
}
This will not select the rest of the fields.

Resources