i'm having trouble when updating one table.
I'm using NextJS
I have these 2 models. The property bank of bank_data_users creates a relation with banks model
model bank_data_users {
id Int #id #default(autoincrement()) #db.UnsignedInt
fullName String? #db.VarChar(255)
userPermissions Int?
bank Int?
bankInfo banks? #relation(fields: [bank], references: [id])
userPermissionsRef users? #relation(fields: [userPermissions], references: [id])
}
model banks {
id Int #id #default(autoincrement()) #db.UnsignedInt
code String? #db.VarChar(255)
bank bank_data_users[]
}
When i try to update it, i get this error
Unknown arg `bank` in data.bank for type bank_data_usersUpdateInput. Did you mean `type`? Available args:
type bank_data_usersUpdateInput {
fullName?: String | NullableStringFieldUpdateOperationsInput | Null
type?: String | NullableStringFieldUpdateOperationsInput | Null
bankInfo?: banksUpdateOneWithoutBankNestedInput
userPermissionsRef?: usersUpdateOneWithoutBankNestedInput
}
So i accessed the index.d.ts that's located at node_modules\.prisma\client\index.d.ts to see the type bank_data_usersUpdateInput. It looks like this
export type bank_data_usersUpdateInput = {
fullName?: NullableStringFieldUpdateOperationsInput | string | null
type?: NullableStringFieldUpdateOperationsInput | string | null
bankInfo?: banksUpdateOneWithoutBankNestedInput
userPermissionsRef?: usersUpdateOneWithoutBankNestedInput
}
Why doesn't it have the bank and userPermissions property?
I'm updating it like this
const id = Number(req.query.id);
await prisma.bank_data_users.update({
where: { id },
data: {bank:body.bank},
});
Related
Nested records
Are records similar to dictionaries where it's a tree of objects with names?
Or records are just a list of simple types
let r = { b = { a = 2 } } // is this possible? if not, how to achieve? is this useful in f#?
For me with discriminated unions it's possible to achieve kind of similar behavior (code below)
// Discriminated union for a card's suit
type Suit = | Heart | Diamond | Spade | Club
let suits = [Heart; Diamond; Spade; Club]
suits
// Discriminated union for playing cards
type PlayingCard =
| Ace of Suit
| King of Suit
| Queen of Suit
| Jack of Suit
| ValueCard of int * Suit
// generating a deck of cards
let deckOfCards =
[
for suit in [Spade; Club; Heart; Diamond] do
yield Ace(suit)
yield King(suit)
yield Queen(suit)
yield Jack(suit)
for value in 2..10 do
yield ValueCard(value, suit)
]
It's kind of similar to a dictionary in python or idk. The code below is dummy
type Customer =
{
FirstName : string
Contacts =
{
WorkPhone : string
MobilePhone : string
}
}
Nested types can be created using anonymous records:
type Customer =
{
FirstName : string
Contacts :
{|
WorkPhone : string
MobilePhone : string
|}
}
let customer =
{
FirstName = "John"
Contacts =
{|
WorkPhone = "123-456-7890"
MobilePhone = "234-567-8901"
|}
}
You can see some patterns in the code, but records are not similar to dictionaries. You can think of them as of classes rather, with strongly typed public properties. If you need to create a dictionary, you have to use one of the available map/dictionary classes or implement your own. Have a look at the Map type for example.
https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-fsharpmap-2.html
type Contact =
{
WorkPhone : string
MobilePhone : string
}
type Customer =
{
FirstName : string
Contacts : Contact
}
let cust : Customer =
{
FirstName = "Joe"
Contacts = { WorkPhone="1800131313"; MobilePhone="0863331311" }
}
The code above shows that you can nest the record types. Aside of using anonymous records as #brianberns suggested, you can declare the data types you plan to nest.
Yes, you can have nested records, but just like in your example with discriminated unions, you need to give a name to the nested type:
type CustomerConracts =
{
WorkPhone : string
MobilePhone : string
}
type Customer =
{
FirstName : string
Contacts: CustomerConracts
}
let c = { FirstName = "John", Contacts = { WorkPhone = "123", Mobile phone = "098" } }
This question already has answers here:
Set start value for AUTOINCREMENT in SQLite
(7 answers)
Closed 5 years ago.
I need the primary key to start from 1000 .how can do it?
public class LoginTable
{
[PrimaryKey, AutoIncrement, Column("_Id")]
public int id { get; set; }
public string info { get; set; }
public string info2 { get; set; }
}
You can modify the sqlite_sequence table and assign whatever starting point you want. If the LoginTable has not been inserted into, you will need to insert a new sqlite_sequence record, otherwise you would need to update the existing sqlite_sequence record.
The sqlite_sequence contains just two fields (name and seq) and does not contain a primary key nor any indexes. name is name of your table and seq is the current used sequence number, the next insert would increment this BEFORE using it.
Example:
using (var db = new SQLiteConnection("foo.sqlite"))
{
db.CreateTable<LoginTable>();
db.Execute("insert into sqlite_sequence (name, seq) values (?, ?);", new object[] { "LoginTable", 999 });
// if LoginTable records already exist, then the `sqlite_sequence` record exists for this table and you need to update it...
//db.Execute("update sqlite_sequence set seq = ? where name = ?;", new object[] { 999, "LoginTable"});
var login = new LoginTable { info = "info1....", info2 = "info2....." };
db.Insert(login);
db.Insert(login);
db.Insert(login);
foreach (var item in db.Table<LoginTable>())
{
Console.WriteLine(item.id);
}
}
Output:
1000
1001
1002
I have an application which stores tasks and I want to add attachments to those tasks.
I have tried three different ways of doing this and don't know if any of them are correct and am looking for advice on where to go:
For example, simplified I have used a table:
+----------------------------------------------------------------------------+
| TaskID Description attachmentString |
+----------------------------------------------------------------------------+
| 1 Task1 "FileName1:::fileLocation;FileName2:::fileLocation" |
| 2 Task2 "FileName3:::fileLocation;FileName4:::fileLocation" |
+----------------------------------------------------------------------------+
This is similar to how profile data is stored in ASP.NET membership.
I have also tried:
+---------------------------+
| TaskID Description |
+---------------------------+
| 1 Task1 |
| 2 Task2 |
+---------------------------+
+------------------------------------------------------+
| AttachmentId Description Location TaskId |
+------------------------------------------------------+
| 1 FileName1 FileLocation 1 |
| 2 FileName2 FileLocation 1 |
+------------------------------------------------------+
If I use the first option, I can just select tasks and get all the attachment data in one SQL call; but it seems cluncky to me to have to then parse the string. Its also not very "relational"
However using an attachment Id, if I want to get the attachments, I either JOIN both tables on attachmentId and then have number of attachments x number of tasks returned. I can have up to 5 attachments so for 50 tasks, it could return 250 rows of which the first columns (from the task table side of the JOIN) are repeated and this seems like a waste. Obviously I have a little more than just description in my table!!!
I have also considered just getting the task data and then just getting the attachment data separately and then joining them in my application. This returns less data than the second option, but requires two calls to the database and that seems wrong too.
I am doing this wrong? Is there a better way? Does anyone have any thoughts on the best way to do this.
I'm not very confident with SQL and maybe I have missed something huge so any pointers would be gratefully received.
The right design is obviously two tables. Having only one table violates the first normal form.
Relating to the load problem, both approaches are correct.
Joining the tables in the sql statement is what most ORM's do to eagerly load related objects. Obviously there is some network traffic overhead, but I think it is acceptable.
Executing two separate sql statements is also correct. You can send them together in one batch to SQL Server to save roundtrips. It has a disadvantage although, you need to perform the join at the client side.
So, are you willing to write more code to save some network traffic?
EDIT:
Given the following table and data:
CREATE TABLE Tasks
(
TaskId int IDENTITY(1,1) PRIMARY KEY,
TaskDescription nvarchar(500) NOT NULL
)
CREATE TABLE TaskAttachments
(
AttachmentId int IDENTITY(1,1) PRIMARY KEY,
TaskId int NOT NULL REFERENCES Tasks(TaskId),
[FileName] nvarchar(500) NOT NULL,
[FileLocation] nvarchar(500) NOT NULL
)
GO
INSERT INTO Tasks VALUES
('Task1'), ('Task2')
INSERT INTO TaskAttachments VALUES
(1, 'FileName1', 'File location 1'),
(1, 'Filename2', 'File location 2'),
(2, 'FileName3', 'File location 3'),
(2, 'Filename4', 'File location 4')
The following classes:
public class TaskAttachment
{
public int AttachmentId { get; set; }
public string FileName { get; set; }
public string FileLocation { get; set; }
}
public class AppTask
{
public int TaskId { get; set; }
public string TaskDescription { get; set; }
public List<TaskAttachment> Attachments { get; set; }
public AppTask()
{
this.Attachments = new List<TaskAttachment>();
}
}
The following class loads the tasks with its attachments by executing two select statements in one single batch:
public class DataLayer
{
private readonly SqlConnection connection;
public DataLayer(SqlConnection connection)
{
this.connection = connection;
}
public List<AppTask> GetTasks()
{
var commandText = #"
SELECT TaskId, TaskDescription FROM Tasks;
SELECT AttachmentId, TaskId, [FileName], FileLocation FROM TaskAttachments;
";
using (var cmd = new SqlCommand(commandText, connection))
using (var reader = cmd.ExecuteReader())
{
var tasks = new List<AppTask>();
while (reader.Read())
{
var task = new AppTask
{
TaskId = reader.GetInt32(0),
TaskDescription = reader.GetString(1)
};
tasks.Add(task);
}
var taskDic = tasks.ToDictionary(x => x.TaskId);
reader.NextResult();
while (reader.Read())
{
var attachment = new TaskAttachment
{
AttachmentId = reader.GetInt32(0),
TaskId = reader.GetInt32(1),
FileName = reader.GetString(2),
FileLocation = reader.GetString(3)
};
var task = taskDic[attachment.TaskId];
task.Attachments.Add(attachment);
}
return tasks;
}
}
}
You can use the above class like this:
using (var cn = new SqlConnection("Data Source=(local);Initial Catalog=Tests;Integrated Security=SSPI"))
{
var dataLayer = new DataLayer(cn);
cn.Open();
var tasks = dataLayer.GetTasks();
}
I have to build a query to get users that did not received and alert about new posts.
My relevant table structure is as follows:
Posts: postId int
Users: userId int, email varchar
PostAlertUsers: postAlertUserId int, postId int, userId int
All related fields have FK constraints between tables.
I've built this query in SQL but couldn't find a way to work in Entity Framework:
SELECT u.email
FROM Users u
INNER JOIN Posts p ON p.userId != u.userId
LEFT JOIN PostAlertUsers pu ON u.userId = pu.userId AND p.postId = pu.postId
WHERE pu.postAlertUserId IS NULL
I've wrote the following EF query, but didn't got the same results:
from u in context.Users
join pu in context.PostAlertUsers on u.userId equals pu.userId into postAlerts
from pa in postAlerts.DefaultIfEmpty()
join p in context.Posts on pa.postId equals p.postId
where pa.userId != u.userId
select u.email;
How can I get the same results using linq to entities. Using the dot syntax (I don't know the correct term for DbSet.Where(x => ...) syntax) would be even better.
Edit:
I want to get all users that didn't have a record on PostAlertUsers for each Post in Posts that isn't from the same user.
Edit 2:
Trying to clarify a bit more:
I want to warn users about new posts from other users only one time for each post and my routine will run every hour to check if there are anyone to send a message.
I want to get all users that aren't already warned about a post so it will not have a record on PostAlertUsers for this user and post combination but will have a record on Posts from a user other that itself.
Example data:
Users
------------------------
userid | email
------------------------
1 | email1#test.com
2 | email2#test.com
3 | email3#test.com
------------------------
Posts (posts are created by users)
------------------------
postId | userId
------------------------
1 | 1
2 | 3
3 | 1
------------------------
PostAlertUsers (every time a user is notified about a new post, one record is added here)
------------------------
postId | userId
------------------------
1 | 2
1 | 3
2 | 1
------------------------
The resulting query would output this data:
Result (using postId and userId to identify what user have to be notified for what post)
---------------------------------
postId | userId | email
---------------------------------
2 | 2 | email2#test.com
3 | 2 | email2#test.com
3 | 3 | email3#test.com
---------------------------------
Edit:
Thanks to AD.Net I've came up with the following:
from u in context.Users
let posts = contexto.Posts.Where(p => p.userId != u.userId)
from p in posts
join pau in context.PostAlertUsers on u.userId equals pau.userId
into alerts
from a in alerts.DefaultIfEmpty()
where a == null || a.postId != p.postId
orderby p.idPost
select new {
p.postId,
u.userId,
u.email
}
edited:
Another attempt from different angle, not sure about performance, might be just as bad as cross-join
from p in context.Posts
let otherUsers = context.Users.Where(u => u.UserId != p.User.UserId)
from u in otherUsers
join pau in alerts on u.UserId equals pau.User.UserId into alert
from a in alert.DefaultIfEmpty()
where a == null || a.Post.PostId != p.PostId
select new {p.PostId, u.Email};
Here's a LinqPad attempt:
void Main()
{
var users = new List<User>{new User{UserId = 1}, new User{UserId = 2}};
var posts = new List<Post>
{
new Post{PostId = 1, User = new User{UserId = 2}},
new Post{PostId = 2, User = new User{UserId = 1}},
new Post{PostId = 3, User = new User{UserId = 2}},
};
var alerts = new List<PostUserAlert>
{
new PostUserAlert{Post = new Post{PostId = 1},
User = new User{UserId = 1}}
};
var result = (from p in posts
let otherUsers = users.Where(u => u.UserId != p.User.UserId)
from u in otherUsers
join pau in alerts on u.UserId equals pau.User.UserId into alert
from a in alert.DefaultIfEmpty()
where a == null || a.Post.PostId != p.PostId
select new {p.PostId, u.UserId}).ToList();
result.Dump();
}
class User
{
public int UserId { get; set; }
public string Email { get; set; }
}
class Post
{
public int PostId { get; set; }
public User User { get; set; }
public List<PostUserAlert> PostUserAlerts { get; set; }
}
class PostUserAlert
{
public Post Post { get; set; }
public User User { get; set; }
}
// Define other methods and classes here
there are 3 database tables (movies, reviews, users)
the reviews table include ( MemeberID, MovieID, Review Text, Rate, ReviewDate)
(the MemeberID, and MovieID in the Review are the FK of the members table and the movies table)
The Movie can have many reviews, and i'm trying to add review to a movie
even I have movie class and the member class, I have a problem, in order to insert review, i need to reference it to movie and users , link them, and i don't know how to do it
this code make a error:
" The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects. "
This is my code...
public bool InsertNewReview(Movie _TheMovie, Member _TheMember, string _Text, byte _Rate, DateTime _ReviewDate)
{
Review ReviewToInsert = new Review()
{
MovieID = _TheMovie.MovieID,
MemberID = _TheMember.MemberID,
Movie = _TheMovie,
Member = _TheMember,
Rate = _Rate,
ReviewDate = _ReviewDate,
ReviewText = _Text
};
videoLib.Reviews.AddObject(ReviewToInsert);
videoLib.SaveChanges();
return true;
}
..
there are more data to insert to the Review class
Images: here
..
and the tables: (the "all columns" isn't a field in database tables)
Images: here
could you try like this
Review ReviewToInsert = videoLib.Reviews.CreateObject();
ReviewToInsert.MovieID = _TheMovie.MovieID
...
...
videoLib.Reviews.AddObject(ReviewToInsert);
videoLib.SaveChanges();
I got a solution, I need to define only the MovieID, MemberID, and not using their object
and use try & catch, to detect if thier the same MovieID (fk) and MemberID (fk) in the same row (because the review don't have is own id in the database)
public bool InsertNewReview(string _MovieID, int _MemberID, string _Text, byte _Rate, DateTime _ReviewDate)
{
try
{
Review ReviewToInsert = new Review()
{
Rate = _Rate,
ReviewDate = _ReviewDate,
ReviewText = _Text,
MovieID = _MovieID,
MemberID = _MemberID
};
videoLib.Reviews.AddObject(ReviewToInsert);
videoLib.SaveChanges();
return true;
}
catch
{
return false;
}
}