EF 7 readonly/hidden columns only for particular rows - c#

I’m looking to convert an existing project to using EF 7. The current user security allows for certain fields of certain rows to be read-only or completely hidden.
For example an ‘admin’ user might be able to read/modify all data from the users table EXCEPT for other administrators. For other administrators, ‘username’ would be read-only, and ‘passwordHash’ would be completely hidden.
Is there a way to do this with EF 7? FluentAPI or something else?
From what I've been able to find with FluentAPI, filtering can be applied to read-only/hide whole rows, or read-only/hide particular columns for ALL rows. I want to read-only/hide particular columns for SOME rows.

Related

How to make a mechanism of column configuration in tables on a website

I use MSSQL, at the moment I was creating a new materialized view in the applications, which contained columns from several different tables. Of course, for such a view, I had to create objects for EFCore, provide a GET endpoint that, using OData, handled pagination, sorting, filtering, etc.
My question is, is there a way to give the user the ability to configure such a table (adding, removing columns), without having to rebuild and deploy the application?
It would be possible to configure such a table in the DB, so that the frontend would know what and what type of columns it should show. Only the possibility of changes in the DB, extension of the materialized view, configuration is at stake.
Anyone encountered something like this?

Incremental ETL on code first many-to-many association table

I'm setting up a data warehouse (in SQL Server) together with our engineers we got almost everything up and running. Our main application also uses SQL Server as backend, and aims to be code first while using the entity framework. In most tables we added a column like updatedAt to allow for incremental loading to our data warehouse, but there is a many-to-many association table created by the entity framework which we cannot modify. The table consists of two GUID columns with a composite key, so they are not iterable like an incrementing integer or dates. We are now basically figuring out the options on how to enable incremental load on this table, but there is little information to be found.
After searching for a while I mostly came across posts which explained how it's not possible to manually add columns (such as updatedAt) to the association table, such as here Create code first, many to many, with additional fields in association table. Suggestions are to split out the table into two one-to-many tables. We would like to prevent this if possible.
Another potential option would be to turn on change data capture on the server, but that would potentially defeat the purpose of code first in the application.
Another thought was to add a column in the database itself, not in code, with a default value of the current datetime. But that might also be impossible / non compatible with the entity framework, as well as defeating the code first principle.
Are we missing anything? Are there other solutions for this? The ideal solution would be a code first solution, or a solution in the ETL process without affecting the base application, without changing too much. Any suggestions are appreciated.

.NET Updating Data in SQL View

I've been asked by my boss to replicate an MS Access feature that we're going to lose shortly after migrating our product to .NET.
The feature is the ability to view and update any data in the database, particularly Tables or Views, in a tabular grid.
I can do it for pure tables that have a identity column because the SqlDataAdapter can auto-generate the relevant CRUD methods on the fly, to fill / update via DataTables.
However, views are somewhat more tricky. SQL Server Management Studio does allow it. If you click 'Edit top xx rows' on a View, it allows you to edit the data in some columns in what looks to be a standard .NET DataGridView - though it feels a bit magical.
So, a few questions:
How does SSMS infer which primary key to use, even if the key is not in the view?
How does SSMS determine which column inside a view can or can not be edited / inserted / deleted etc.?
What would be my best option to replicate this inside a .NET application?
Is it possible to connect a DataGridView to an old style oledb / obdc connection that has a constant direct connection to the database?
Any guidance as normal will be highly appreciated.
Marlon
SQL Server views can be updated just as if they were a single table, as long as they conform to certain conditions.
From the documentation:
Updatable Views
You can modify the data of an underlying base table through a view, as
long as the following conditions are true:
Any modifications, including UPDATE, INSERT, and DELETE statements,
must reference columns from only one base table.
The columns being modified in the view must directly reference the
underlying data in the table columns. The columns cannot be derived in
any other way, such as through the following:
An aggregate function: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV,
STDEVP, VAR, and VARP.
A computation. The column cannot be computed from an expression that
uses other columns. Columns that are formed by using the set operators
UNION, UNION ALL, CROSSJOIN, EXCEPT, and INTERSECT amount to a
computation and are also not updatable.
The columns being modified are not affected by GROUP BY, HAVING, or
DISTINCT clauses.
TOP is not used anywhere in the select_statement of the view together
with the WITH CHECK OPTION clause.
The previous restrictions apply to any subqueries in the FROM clause
of the view, just as they apply to the view itself. Generally, the
Database Engine must be able to unambiguously trace modifications from
the view definition to one base table. For more information, see
Modify Data Through a View.
I don't believe SSMS is doing anything special - editing the contents of a view offers exactly the same functionality as editing the contents of a table. If the user attempts to make a change that does not conform to the above conditions, SSMS will likely display an error.
How does SSMS infer which primary key to use, even if the key is not in the view?
It doesn't. SQL Server does since only one underlying table can be edited at a time.
How does SSMS determine which column inside a view can or can not be edited / inserted / deleted etc.?
Again, it's SQL Server that determines this, not SSMS.
What would be my best option to replicate this inside a .NET application?
As long as all your views conform to the above conditions, simply do the same as you're doing for tables, but be ready to handle the errors from users doing something they can't (this implies some user training will be required, just as it would be if they were using SSMS directly).

C#/SQL changing logging - best methods

Not sure if this question is suitable for StackOverflow as it's much more 'general'. Basically, I have a database driven business application made in ASP.NET and C#, which'll be used by around 20 members of a company. A crucial aspect of this is auditing - I need to log on any changes to any of the tables, and have them viewable by senior members of the staff.
My current solution uses SQL triggers, but I need to create something much more robust and user friendly. The database is gigantic, with a lot of tables with relations etc, and the audits currently are very uninformative to the users - telling the staff that x user modified an order to have a customer of ID of 837 is near enough useless - I need to be able to dictate which field is displayed in the audit log.
My idea is to create a class in my code that'll handle all these, and somehow map out what fields to display to the user, and also somehow tell the code which table was modified and which record.
Can anyone offer any general advice on how to do what I want, and whether it's actually possibile? I'm a heavy user of LINQ-to-SQL in my code, so I'm hoping that'll help...
You could also try using DoddleAudit for your needs. It provides automatic auditing of all inserts/updates/deletes for any table in your database with a single line of code, including:
What table was modified?
What fields changed?
Who made the change?
When did it occur?
You can find it here: http://doddleaudit.codeplex.com/
I've had similar audit requirements for a healthcare application, which used linq-to-sql for data access.
One way to do it centrally in Linq-to-sql is to override SubmitChanges in the data context class. Before submitting the changes, call GetChangeSet() to get data about the pending changes. Then add change tracking information as appropriate to a relevant log table before calling base.SubmitChanges(). In my application I used an xml column to be able to store change data for different tables in a structured manner, without having to create special history tables for each table in the system.
You could also try using SQL Server 2008's Change Data Capture feature. It basically captures inserts, updates and deletes on the desired tables, and stores changes made into a separate set of relational tables.
http://www.mssqltips.com/sqlservertip/1474/using-change-data-capture-cdc-in-sql-server-2008/

How to get Nhibernate to handle non existing database columns gracefully

I am working on a project that requires the use of multiple databases that for the most part are completely identical but some columns might be missing. How do you get NHibernate to handle this for instance i have a table with 4 columns an index and 2 data coloumns that will always be availible but a singe customer does not want the column in their database.
as this is part of a legacy application migration i do not have the luxury of dictating the database format or even change the databases. anybody have any ideas of how to do this. I cannot get NHibernate shards to work with this either.
KR
Nicky
I don't know of a way to tell NHibernate to ignore columns that are otherwise mapped.
I would look at creating multiple mappings files for the different databases and then depending on your environment configure your SessionFactory using the correct mapping files.
This may seem like a little more work to setup initially but it makes it very clear that in database X you have columns A-B-C and in database Y you only have columns A-B.

Categories