Not exposing IQueryable and not violating OC principle [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I was reading about the repository pattern the last few days and everyone talking about it do not expose IQueryable from repository like this (like here and here):
public interface ICustomersRepository
{
IQueryable<Customer> Customers{ get; }
}
And it is accepted by large amount of developers to avoid this.
But when it comes to filtering large amount of data and custom filters from UI (like a report with over 10 filter options for searching in data over 1 million records) is IQueryable?
Especially when there is a framework and other low-level developers are using the repository for developing custom reports. They can not always use GetAll for this purpose.
So as mentioned in other threads like this or this, I should have methods for each one of the reports that I have in my repositories, and they should return IEnumerable. Here is what is not clear to me:
If I have a new report I have to change my repository for that and add a new method. And if I change my repository I've violated the Open/Close principle.
Here is my problem: I don't want to expose Iqueryable and on the other hand, I don't want to change my repository for every report.

A repository is an abstraction over your Data Access Layer (DAL). In Java, they are also known as DAOs (Data Access Objects). So, exposing IQueryable<T> in a repository is bad practice because of this reason, you are tying LINQ queries to the client code.
So, to fix it you should create an object which would follow the command pattern with all the filtering options you support. Then return a List<T> or any sorted collection you want to use (maybe IList<T> is more appropriate).
An example
class BookFilter
{
public string NameStartsWith { get; set; }
public string ISBN { get; set; }
public DateTime PublishedAfter { get; set; }
// ....
}
public interface IBookRepository
{
IList<Book> Filter(BookFilter filter);
}

Related

Data Access best practices [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have different Models in my Asp.Net Core application. Is it recommended to do SQL queries inside IActionResult Action methods? or is a better to have a seperate class do all work in terms of fetching data for each of the models and return the result to IActionResult method where we can display Return View()?
I have a static Utility class. If I were to have a class for each model to fetch data I would need access to IHttpContextAccessor but i cant assign that in a static class. What type of class would be the way to go?
You can go for the repository pattern (https://martinfowler.com/eaaCatalog/repository.html), adding a generic repository (one single class) or a concrete repository (one per model).
Another solution would be using partial classes, to add data access logic in your model classes.
In example:
public partial class MyModel
{
public string Name { get; set; }
}
public partial class MyModel
{
//add data access here
}
Also to identify them, you could add an extension to model class files, like ".cs.da" (then you would have "MyModel.cs" and "MyModel.cs.da" files) and nest them using File nesting extension: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.FileNesting

Changing an Existing class - Best Practice Open/Closed Principle [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I am trying to figure out the best way to change an existing class.
So the class is called ExcelReport and it has one method Create(data,headings). This is live and used in many places. Now recently I want to change the method so I can format columns in Excel.
Create(data, headings, columnformats)
So as not to upset my existing programs the best I can come up with is to add another method Create2(data,headings,columnformats) to the class.
I got a lot of suggestions saying I should modify the existing class with a overloaded method, which I did. But does this not break the Open/Close Principle as my existing class was in production?
Should I have created a new class ExcelReport2(and Interface) with the new improved method and passed this into my new program using dependency injection?
OCP
In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification";[1] that is, such an entity can allow its behaviour to be extended without modifying its source code.
Your solution
You will most likely want to create more options later on for this.
And since you asked for an open/closed principle answer we need to take that into account (open for extension, closed for change).
A more robust alternative is to create a new overload:
void Create(CreationOptions options);
Looks trivial, right? The thing is that any subclass can introduce their own options like MyPinkThemedFormattedCellsCreationOptions.
So your new option class would look like this as of now:
public class CreationOptions
{
public SomeType Data { get; set; }
public SomeType Headings { get; set; }
public SomeType[] ColumnFormats { get; set; }
}
That's open for extension and closed for change as new features doesn't touch the existing API, since now you only have to create sub classes based on CreationOptions for new features.

Using IList, List, ICollection for 1 to n relationships in EF Core [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 months ago.
The community reviewed whether to reopen this question 2 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
What is the best practice to define a One-to-Many relationship in EF Core?
Is it recommended to generally use lists, as these offer more functionalities?
Then rather the interface IList instead of List, as it does not define the implementation?
If it does matter, on what criteria should I pick one or the other?
Microsoft suggests the following
https://learn.microsoft.com/en-us/ef/core/modeling/relationships
public class Blog
{
public int BlogId { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
Whereas
http://www.entityframeworktutorial.net/efcore/configure-one-to-many-relationship-using-fluent-api-in-ef-core.aspx
https://www.learnentityframeworkcore.com/configuration/one-to-many-relationship-configuration
suggest ICollections
Is the following answer of 2011 still valid in EF Core?
https://stackoverflow.com/a/7655974/10148774
Your decision should depend on the operations that your use case will need.
In general, you have three main options:
IEnumerable<> for a list of objects that only needs to be iterated through (no additional operations such as modifications).
ICollection<> for a list of objects that needs to be iterated through and modified.
IList<> for a list of objects that needs to be iterated through, modified, sorted, access by index...
Now this may lead you to the following question: "So I will always use List because it provides the most functionality". In this case you should keep in mind that this option has the most overhead and a good object-oriented practice is to program towards the interface and not the implementation. Implementations can and will change.
Long story short: There is no golden rule here, you need to analyze and make the proper trade-offs for your specific scenario in order to make the best choice.

OOP interaction with database [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
If object oriented programming is focused on objects, which consist of methods and data, what is the best OOP-focused approach to working with databases, using C#?
For example, I want to log something using C# classes, and record the logs in a SQL table. All other factors being neutral, would it be more "proper," object-oriented speaking, to do:
Create a class for what's being logged, and include methods for database access
(The methods are tied closely to data)
public class Activity
{
public string ActivityProperty { get; set; }
public void SQLMethod1() {}
public void SQLMethod2() {}
}
...or,
Create a class for what's being logged, and create a class for database access
(Methods are not closely tied to data, but the way data is accessed is treated itself as an object, i.e. referencing EF or another ORM)
public class Activity
{
public string ActivityProperty { get; set; }
}
public class SQLMethods
{
public string SQLProperty { get; set; }
public void SQLMethod1(Activity activityParam) { }
public void SQLMethod2(Activity activityParam) { }
}
...or, perhaps a better design would be more "object-oriented"?
Generally speaking, I prefer not to put database access logic into classes because it hinders your ability to use them in other scenarios in which data access is not required. So I think your second option is the more flexible one.
However, if you are already aware of ORM solutions such as Entity Framework, I would suggest using one of those. EF takes an approach closer to your second one in which you use POCOs (plain old C# classes) and other EF classes take care of moving data from those objects into the database and back.
So overall my suggestion would be to use Entity Framework with the code first methodology.

Storing arbitrary complex objects in c# to database [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am currently programming to multiple API's. Till now I have created classes that use EF syntax (id = classNameId etc...) and convert whatever item is being returned to EF object. Since I'm using the C# Wrappers (created by whatever company created the API) for the API's I can't simply alter whatever class it is that I want to store to the database to use EF Syntax. Is there any project that would allow me to dynamically generate tables and columns for any generic object using run time reflection?
Keep in mind that many of the complex objects have within them complex objects.
As of right now I'm considering writing a script to generate inherited classes for each of the Complex Types (identified via reflection) and inserting a Id (and whetever other information EF would need to generate DB) into the inherited class. This would get a little complicated as it would require implicit conversions for Ienumerable to Ienumerable.
Any help would be greatly appreciated.
Thank You.
What you actually need is some schema-less database, like MongoDB or RavenDb instead of relational. These allows to do exactly what you said in the title: to store arbitraty complex objects in db.
You may want to look at OrmLite and see if it meets your reqs.
public class SimpleExample
{
public int Id { get; set; }
public string Name { get; set; }
}
//Set once before use (i.e. in a static constructor).
OrmLiteConfig.DialectProvider = new SqliteOrmLiteDialectProvider();
using (IDbConnection db = "/path/to/db.sqlite".OpenDbConnection())
using (IDbCommand dbConn = db.CreateCommand())
{
dbConn.CreateTable<SimpleExample>(true);
dbConn.Insert(new SimpleExample { Id=1, Name="Hello, World!"});
var rows = dbConn.Select<SimpleExample>();
Assert.That(rows, Has.Count(1));
Assert.That(rows[0].Id, Is.EqualTo(1));
}

Categories